Class attributes, instances and metaclass __getattribute__

Pedro Werneck pedro.werneck at terra.com.br
Tue Aug 8 08:47:38 EDT 2006


Hi

On 8 Aug 2006 00:10:39 -0700
"Michele Simionato" <michele.simionato at gmail.com> wrote:

> To me, it seems consistent. As said in
> http://www-128.ibm.com/developerworks/linux/library/l-pymeta2/
> 
> """The availability of metaclass attributes is not transitive; in
> other words, the attributes of a metaclass are available to its
> instances, but not to the instances of the instances. Just this is the
> main difference between metaclasses and superclasses."""


Well... I'm not talking about metaclass attributes... that's perfectly
consistent, agreed.

I'm saying that when the class implements a custom __getattribute__,
when you try to access the instance attributes from itself, it uses it.
But if the class is a metaclass, instances of its instances have acess
to the attribute anyway, but don't use the custom __getattribute__ you
implemented. 

Like the example I mentioned on the previous mail, or (I think in this
case it's more obvious):

>>> class N(type):
...     def __getattribute__(cls, attr):
...             print 'using N.__getattribute for "%s"'%(attr)
...             return type.__getattribute__(cls, attr)
... 
>>> class M(type):
...     __metaclass__ = N
... 
>>> class C(object):
...     __metaclass__ = M
... 
>>> M.x = 'foo'
>>> M.x
using N.__getattribute for "x"
'foo'
>>> C.x
'foo'


So, in both cases I have access to the class attribute; but in one case
it's using the bound M.__getattribute__ implemented at the base
metaclass, but not in the other. It was supposed to use it after the
bound 'C.__getattribute__' raises AttributeError as expected, but it
doesn't...

It's inconsistent, but seems a reasonable decision to me since someone
can easily mess with descriptors doing with this... but, someone else
involved with Python dev I talked about thinks it may be a bug.

And, I'm curious anyway... is it possible to customize attribute access
in this case in any other way ? What really happens here ?

>From the typeobject.c source code, seems like when the metaclass
implements __getattribute__, it uses type.__getattribute__ in this case,
but I'm not sure.


> Since this happens for real attributes, it looks natural that the same
> should happen for 'virtual' attributes implemented via '__getattr__'
> or '__getattribute__'.

Well... as I think it's clear now, the case you mentioned is not exactly
what I'm talking about, but it's good you mentioned about 'virtual'
attributes, because in this case we have another problem, it's
inconsistent too and there's no reason for it...

>>> class M(type):
...     def __getattr__(cls, attr):
...             if attr == 'x':
...                     return 'foo'
... 
>>> class C(object):
...     __metaclass__ = M
... 
>>> C.y = 'bar'
>>> C.x
'foo'
>>> C.y
'bar'
>>> o = C()

>>> o.x 
...
AttributeError: 'C' object has no attribute 'x'
>>> o.y
'bar'
>>> 

So... both 'x' and 'y' are class attributes, but 'x' is a virtual
attribute implemented with M.__getattr__. From the instance I have
access to 'y' but not to 'x'.



Regards,

-- 
Pedro Werneck



More information about the Python-list mailing list