Customizing class attribute access in classic classes

Steven D'Aprano steve+comp.lang.python at pearwood.info
Sun Oct 30 05:23:26 EDT 2011


On Sat, 29 Oct 2011 14:06:12 -0700, Geoff Bache wrote:

> Hi,
> 
> I'm wondering if there is any way to customize class attribute access on
> classic classes?
> 
> So this works:
> 
> class Meta(type):
>     def __getattr__(cls, name):
>         return "Customized " + name
> 
> class A:
>     __metaclass__ = Meta
> 
> print A.blah
> 
> but it turns A into a new-style class.

And why is this a problem?

In any case, metaclasses work for classic classes. Metaclasses go back to 
pre-Python 1.5, long before new-style classes and type unification.

http://www.python.org/doc/essays/metaclasses/

You just have to do a lot more work:


class Meta:
    def __init__(self, name, bases, namespace):
        self.__name__ = name
        self.__bases__ = bases
        self.__dict__ = namespace
    def __str__(self):
        return "<Meta instance>"
    __repr__ = __str__
    def __getattr__(self, name):
        return "Customized " + name
    def __call__(self):
        return self

(The purpose of the __str__ and __repr__ methods is to make it possible 
to experiment in the interactive interpreter, without a lot of mysterious 
and puzzling "str object is not callable" TypeErrors. Trust me on this.)

And in use:

>>> class Spam:
...     __metaclass__ = Meta
...     a = 1
... 
>>> Spam.b
'Customized b'


But note that using classic classes, there is no equivalent of 
__getattribute__ or descriptors, so there is no way to customize access 
of an attribute which actually does exist:

>>> Spam.a
1


-- 
Steven



More information about the Python-list mailing list