Odd behaviour of dir(object) with metaclasses.
Dirk Gerrits
dirk at gerrits.homeip.net
Wed Apr 9 15:54:19 EDT 2003
Hi,
I am a bit puzzled by the behaviour of the dir builtin. I'll illustrate
this with the following Python shell session:
>>> class MetaBase(type):
def mb(self):
print self
>>> class MetaDerived(MetaBase):
def md(self):
print self
>>> class Base(object):
__metaclass__ = MetaBase
def b(self):
print self
>>> class Derived(Base):
__metaclass__ = MetaDerived
def d(self):
print self
>>> b = Base()
>>> d = Derived()
>>> def not_magic(str):
return not (str.startswith("_") or str.endswith("_"))
>>> filter(not_magic, dir(b))
['b']
>>> filter(not_magic, dir(d))
['b', 'd']
Nothing out of the ordinary here, just as I would expect. But lets take
a look at the classes now:
>>> filter(not_magic, dir(Base))
['b']
>>> filter(not_magic, dir(Derived))
['b', 'd']
Perhaps its just me, but I think this is really odd. The way I would
expect it, dir should list the accessable attributes of the object. And
that would mean:
(1) its own attributes
(2) its class's attributes and recursively of its class's bases
(3) (if it's a class object) recursively the attributes of its bases
For b and d, the dir listings are clearly correct. But Base's and
Derived's the dir listings are incomplete, they don't seem to take (2)
into account:
>>> Base.mb() # No AttributeError
<class '__main__.Base'>
>>> Derived.mb() # Idem
<class '__main__.Derived'>
>>> Derived.md() # Dito
<class '__main__.Derived'>
Perhaps I just don't fully understand what dir does. The first bit in
the docs says:
Return an alphabetized list of names comprising (some of) the
attributes of the given object, and of attributes reachable from it:
This would seem to correspond with my feeling of what its supposed to
do, but doesn't. However, reading further, we see that the current
behaviour is indeed as it is documented:
No argument: the names in the current scope.
Module object: the module attributes.
Type or class object: its attributes, and recursively the
attributes of its bases.
Otherwise: its attributes, its class's attributes, and recursively
the attributes of its class's base classes.
Why is there an unnatural (IMHO) distinction between type/class objects
and other non-module objects? I assume that a class's class is not
considered become dir comes from the pre-metaclass era? Shouldn't the
docs really read
Return an alphabetized list of names comprising (some of) the
attributes of the given object, and of attributes reachable from it:
No argument: the names in the current scope.
Module object: the module attributes.
Otherwise: its attributes, its class's attributes, and recursively
the attributes of its class's base classes. And if it's a class
object, also the attributes of its own base classes recursively.
?
(Or something with the same meaning but in a less confusing wording. ;))
I hope you'll be able to clarify these things for me a bit.
Cheers,
Dirk Gerrits
More information about the Python-list
mailing list