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
[email protected]
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe:
http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com