[Python-Dev] operator.is*Type

Michael Foord fuzzyman at voidspace.org.uk
Wed Feb 22 22:00:57 CET 2006


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'>
>>


More information about the Python-Dev mailing list

AltStyle によって変換されたページ (->オリジナル) /