Automatic Attribute Assignment during Class Inheritance

gizli mehmetf at gmail.com
Thu Sep 10 02:09:04 EDT 2009


On Sep 9, 9:00 pm, Steven D'Aprano
<ste... at REMOVE.THIS.cybersource.com.au> wrote:
> On Wed, 09 Sep 2009 20:14:33 -0700, gizli wrote:
> > I do not want to force the consumers of this framework to write this
> > obscure line of code. I was wondering if it is possible (at class
> > definition time) to capture the fact that MyTask extends Task and
> > automatically insert the polymorphic_identity key into the
> > __mapper_args__ class attribute (with value set to __name__).
>
> > So far, I have not been able to do anything because during class
> > definition time, there is no a lot of variables I can access. *self*
> > obviously does not work. __name__ and __class__ are also useless.
>
> Class definitions are controlled by the metaclass, which is fairly deep
> magic but not entirely impenetrable. Once you've defined a metaclass to
> use, the consumers will only need to say:
>
> class MyTask(Task):
>     __metaclass__ = MyMetaclass
>
> which is less obscure than the alternative. You may even be able to have
> Task use the metaclass, in which case MyTask doesn't need to do anything
> special at all. (I think.)
>
> Another alternative is to use a class decorator:
>
> # You write this and provide it in your API.
> def mapper(cls):
>     cls.__mapper_args__ = dict(polymorphic_identity=cls.__name__)
>     return cls
>
> # The consumer writes this.
> @mapper
> class MyTask(Task):
>     pass
>
> Decorator syntax for classes only works for Python 2.6 or better. In 2.5,
> the consumer would need to write:
>
> class MyTask(Task):
>     pass
> MyTask = mapper(MyTask)
>
> --
> Steven

Steven, thank you. __metaclass__ was exactly what I was looking for.
After a few documents later, I came up with this code:

class PolymorphicSetter(type):
    def __new__(cls, name, bases, dictionary):
        dictionary['__mapper_args__'] = name
        return type.__new__(cls, name, bases, dictionary)

and set this in my Task class:

__metaclass__ = PolymorphicSetter

Also, thank you for the class decorator code. That is what I meant by
class wrapper :) I will keep that as a reference as well.



More information about the Python-list mailing list