Is there a consensus on how to check a polymorphic instance?
Steven Bethard
steven.bethard at gmail.com
Mon Nov 22 23:32:57 EST 2004
Mike Meng wrote:
> I'm a newbie Python programmer with a C++ brain inside. I have a
> lightweight framework in which I design a base class and expect user to
> extend. In other part of the framework, I heavily use the instance of
> this base class (or its children class). How can I ensure the instance
> IS-A base class instance, since Python is a fully dynamic typing
> language?
The short answer is that if you want to ensure an instance is-a subclass
of the base class, you should use isinstance:
>>> class HasF(object):
... def f(self):
... raise NotImplementedError
...
>>> class SubHasF(HasF):
... def f(self):
... return self.__class__
...
>>> class NonsubHasF(object):
... def f(self):
... return self.__class__
...
>>> isinstance(SubHasF(), HasF)
True
>>> isinstance(NonsubHasF(), HasF)
False
However it's often not necessary to go this route. Consider:
>>> class HasNoF(object):
... pass
...
>>> def use_c(c):
... try:
... f = c.f
... except AttributeError:
... raise TypeError('argument to use_c must have an f method')
... return f()
...
>>> use_c(SubHasF())
<class '__main__.SubHasF'>
>>> use_c(NonsubHasF())
<class '__main__.NonsubHasF'>
>>> use_c(HasNoF())
Traceback (most recent call last):
File "<interactive input>", line 1, in ?
File "<interactive input>", line 5, in use_c
TypeError: argument to use_c must have an f method
Is it really necessary that the classes passed to your equivalent of
'use_c' are actually subclasses of your equivalent to 'HasF'? Or is it
just necessary that they support the appropriate methods? If it's the
second, I would just test for the appropriate methods and catch the
AttributeErrors (and possibly the TypeError that's thrown if 'f' isn't
callable).
If you can give a little more detail on your particular example, I (and
others) can probably give you more helpful suggestions...
Steve
More information about the Python-list
mailing list