Question about accessing class-attributes.
Michele Simionato
mis6 at pitt.edu
Tue Apr 29 17:21:56 EDT 2003
"Bjorn Pettersen" <BPettersen at NAREX.com> wrote in message news:<mailman.1051637056.20383.python-list at python.org>...
> > From: Alex Martelli [mailto:aleax at aleax.it]
> [...]
> Here's the case I'm confused about:
>
> >>> class meta(type):
> ... def getattr (cls, name):
> ... if name == ' len ':
> ... print "meta. getattr (' len ')"
> ... return lambda: 42
> ... else:
> ... print 'meta. getattr ', name
> ... return name
> ...
> >>> class S(object):
> ... metaclass = meta
> ...
> >>> S. len ()
> meta. getattr (' len ')
> 42
> >>> len(S)
> Traceback (most recent call last):
> File "<stdin>", line 1, in ?
> TypeError: len() of unsized object
> >>>
>
> I was told that special method "foo(x, arg)" was implemented as
> "type(x). foo (x, arg)", which doesn't seem to be the case always...
> Compare:
>
> >>> class meta(type):
> ... def len (cls):
> ... return 42
> ...
> >>> class S(object):
> ... metaclass = meta
> ...
> >>> S. len ()
> 42
> >>> len(S)
> 42
> >>>
>
> So, it looks like it's looking up len in the metaclass, but not
> falling back on getattr when it isn't there?
I am sure Alex is going to answer, but since you asked me a related
question in another thread ...
Finally, now I see where is the source of the confusion:
len(S) fails because meta.__len__ is NOT defined in
you first example. The point is that __getattr__ works on instances of
meta, NOT on meta itself, therefore S.__len__ is recognized thanks
to __getattr__, but NON meta.__len__
In order to recognize meta.__len__ you must define __getattr__ on the
metaclass of meta, i.e. the meta-metaclass of S:
class metameta(type):
def __getattr__(cls, name):
if name == '__len__':
print "metameta.__getattr__(' len ')"
return lambda cls: 42
else:
print 'metameta.__getattr__', name
return name
class meta(type):
__metaclass__=metameta
class S(object):
__metaclass__ = meta
print type(S).__len__(S)
with output
metameta.__getattr__(' len ')
42
I must say, however, that len(S) is not *literally* type(S).__len__(S):
print len(S)
Traceback (most recent call last):
File "<stdin>", line 18, in ?
TypeError: len() of unsized object
I think Python looks if __len__ is defined in the meta-class and
if not, it does raise an exception. It does not know that there is
a __getattr__ in the meta-metaclass, unless you invoke the metaclass literally
as in type(S).__len__(S).
I did not understood your point in the other thread, I didn't imagine
you where thinking about meta-metaclasses. As you see, there are
situations where they may be useful, i.e. in the customization of
metaclasses, but most people don't think at this level yet ;)
Cheers,
Michele
More information about the Python-list
mailing list