Raymond Hettinger wrote: > [Ian Bicking] >> They seem terribly pointless to me. > > FWIW, here is the script that had I used while updating and improving > the two functions (can't remember whether it was for Py2.3 or Py2.4). > It lists comparative results for many different types of inputs. > Since perfection was not possible, the goal was to have no false > negatives and mostly accurate positives. IMO, they do a pretty good > job and are able to access information in not otherwise visable to > pure Python code. With respect to user defined instances, I don't > care that they can't draw a distinction where none exists in the first > place -- at some point you have to either fallback on duck-typing or > be in control of what kind of arguments you submit to your functions. > Practicality beats purity -- especially when a pure solution doesn't > exist (i.e. given a user defined class that defines just __getitem__, > both mapping or sequence behavior is a possibility). > But given :
True True Instance w getitem <type 'instance'> True True NewStyle Instance w getitem <class '__main__.cng'> True True [] <class UserList.UserList at 0x00F11B70> True True {} <type 'instance'> (Last one is UserDict) I can't conceive of circumstances where this is useful without duck typing *as well*. The tests seem roughly analogous to : def isMappingType(obj): return isinstance(obj, dict) or hasattr(obj, '__getitem__') def isSequenceType(obj): return isinstance(obj, (basestring, list, tuple, collections.deque)) or hasattr(obj, '__getitem__') If you want to allow sequence access you could either just use the isinstance or you *have* to trap an exception in the case of a mapping object being passed in. Redefining (effectively) as : def isMappingType(obj): return isinstance(obj, dict) or (hasattr(obj, '__getitem__') and hasattr(obj, 'keys')) def isSequenceType(obj): return isinstance(obj, (basestring, list, tuple, collections.deque)) or (hasattr(obj, '__getitem__') and not hasattr(obj, 'keys')) Makes the test useful where you want to know you can safely treat an object as a mapping (or sequence) *and* where you want to tell the difference. The only code that would break is use of mapping objects that don't define ``keys`` and sequences that do. I imagine these must be very rare and *would* be interested in seeing real code that does break. Especially if that code cannot be trivially rewritten to use the first example. All the best, Michael Foord > > ---- Analysis Script ---- > > from collections import deque > from UserList import UserList > from UserDict import UserDict > from operator import * > types = (set, > int, float, complex, long, bool, > str, unicode, > list, UserList, tuple, deque, > ) > > for t in types: > print isMappingType(t()), isSequenceType(t()), repr(t()), repr(t) > > class c: > def __repr__(self): > return 'Instance w/o getitem' > > class cn(object): > def __repr__(self): > return 'NewStyle Instance w/o getitem' > > class cg: > def __repr__(self): > return 'Instance w getitem' > def __getitem__(self): > return 10 > > class cng(object): > def __repr__(self): > return 'NewStyle Instance w getitem' > def __getitem__(self): > return 10 > > def f(): > return 1 > > def g(): > yield 1 > > for i in (None, NotImplemented, g(), c(), cn()): > print isMappingType(i), isSequenceType(i), repr(i), type(i) > > for i in (cg(), cng(), dict(), UserDict()): > print isMappingType(i), isSequenceType(i), repr(i), type(i) > > > > ---- Output ---- > > False False set([]) <type 'set'> > False False 0 <type 'int'> > False False 0.0 <type 'float'> > False False 0j <type 'complex'> > False False 0L <type 'long'> > False False False <type 'bool'> > False True '' <type 'str'> > False True u'' <type 'unicode'> > False True [] <type 'list'> > True True [] <class UserList.UserList at 0x00F11B70> > False True () <type 'tuple'> > False True deque([]) <type 'collections.deque'> > False False None <type 'NoneType'> > False False NotImplemented <type 'NotImplementedType'> > False False <generator object at 0x00F230A8> <type 'generator'> > False False Instance w/o getitem <type 'instance'> > False False NewStyle Instance w/o getitem <class '__main__.cn'> > True True Instance w getitem <type 'instance'> > True True NewStyle Instance w getitem <class '__main__.cng'> > True False {} <type 'dict'> > True True {} <type 'instance'> > > _______________________________________________ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com