Mailing List Archive

add type predicates to types module?
This is a really good idea. I know I've got type predicates of many
different flavors in code I've been working on recently. The tough
question, I think, is how to decide which predicates are needed and
how to implement them.

The folkloric "file-like object" type is a good example. When people
say "file-like object" they mean an object that responds in a
reasonable way to the particular subset of methods on a builtin file
object that they are interested in.

isSequence might be a better example, since you want to capture
instances that implement the sequence protocol along with tuples,
lists, and strings. I use:

def isSequence(s):
try:
0 in s
except TypeError:
return 0
else:
return 1

def isCallable(obj):
if type(obj) in (types.BuiltinFunctionType,
types.BuiltinMethodType, types.LambdaType,
types.MethodType):
# XXX could include types.UnboundMethodType
return 1
if type(obj) == types.InstanceType:
return hasattr(obj, '__call__')
return 0

In the particular application I needed, I know I would not want to
include UnboundMethodTypes. In the general case, though, I think it
should be included.

Jeremy
add type predicates to types module? [ In reply to ]
Jeremy Hylton wrote:
>
> This is a really good idea. I know I've got type predicates of many
> different flavors in code I've been working on recently. The tough
> question, I think, is how to decide which predicates are needed and
> how to implement them.
>
> The folkloric "file-like object" type is a good example. When people
> say "file-like object" they mean an object that responds in a
> reasonable way to the particular subset of methods on a builtin file
> object that they are interested in.
>
> isSequence might be a better example, since you want to capture
> instances that implement the sequence protocol along with tuples,
> lists, and strings. I use:
>
> def isSequence(s):
> try:
> 0 in s
> except TypeError:
> return 0
> else:
> return 1

I tried this a while back but then concluded that the meaning
of "is sequence" can mean different things in different situations,
e.g. sometimes I need the object to have a length, at other times
I need __getitem__ (this is what "in" uses).

Note that the above test fails for dictionary types, but let's
dictionary like instances pass.

I think a more generic API is needed; one that allows you to
define the slots/special methods you really need (we'd have to
map the special methods to slots for simplicity). Something
like
has_interface(obj,('__getitem__','__len__'))

> def isCallable(obj):
> if type(obj) in (types.BuiltinFunctionType,
> types.BuiltinMethodType, types.LambdaType,
> types.MethodType):
> # XXX could include types.UnboundMethodType
> return 1
> if type(obj) == types.InstanceType:
> return hasattr(obj, '__call__')
> return 0

There already is a builtin function iscallable() that does pretty
much what you've coded in Python.

> In the particular application I needed, I know I would not want to
> include UnboundMethodTypes. In the general case, though, I think it
> should be included.

... this is a special case I guess. iscallable(obj) and a type
check could be combined to handle it.

--
Marc-Andre Lemburg Y2000: 272 days left
---------------------------------------------------------------------
: Python Pages >>> http://starship.skyport.net/~lemburg/ :
---------------------------------------------------------
add type predicates to types module? [ In reply to ]
On Sat, 3 Apr 1999 10:59:36 +0200, M.-A. Lemburg <mal@lemburg.com> wrote:
>Jeremy Hylton wrote:
>>
>> The folkloric "file-like object" type is a good example. When people
>> say "file-like object" they mean an object that responds in a
>> reasonable way to the particular subset of methods on a builtin file
>> object that they are interested in.

Er, doesn't this point out one of the inherent flaws with this scheme? You
don't really want to know the type of the item, you want to be able to do
certain things with it. So why not do

try:
whatever...
except TypeError:
whatever you do if you're given the wrong type

In other words, try and trap exceptions rather than test beforehand.

That tends to be how C++ "generic programming" works. Write templates using
the operations you need - the templates won't compile when used with incorrect
types. We're just replacing a compile time check with a runtime one, because
Python uses dynamic typing in place of C++'s static model.

Paul Moore.