[Python-3000] PEP Draft: Class Decorators

Brett Cannon brett at python.org
Sat Mar 10 03:23:51 CET 2007


[SNIP]
> class FormFactory(Form):
>     id_to_form = {} # { account_id : { form_id : form_class } }
>     @staticmethod
>     def register(cls, account_id, form_id):
>         FormFactory.id_to_form.setdefault(cls.account_id, {})
>         assert form_id not in FormFactory.id_to_form[cls.account_id], form_id
>         FormFactory.id_to_form[cls.account_id][form_id] = cls
>         # return the class unchanged
>         return cls
>
> @FormFactory.register(account_id=17, form_id=3)
> class FormCaptureA(object):
>     # .. cgi param to sql mapping defined, etc

I don't think this example works.  You have a method call that is
lacking its first argument (did you meant to have it be a
classmethod?).  Plus that call itself will just return FormFactory for
the decorator which itself does not define __call__ and thus will
raise an exception when the decorator is called with FormCapture.  I
think you meant something like the following::

class FormFactory(Form):
   id_to_form = {} # { account_id : { form_id : form_class } }

   @classmethod
   def register(cls, account_id, form_id):
       def inner(to_decorate):
           FormFactory.id_to_form.setdefault(cls.account_id, {})
           assert form_id not in FormFactory.id_to_form[cls.account_id], form_id
           FormFactory.id_to_form[cls.account_id][form_id] = cls
           # return the class unchanged
           return to_decorate
        return inner


Otherwise define a __call__ method on FormFactory or use
functools.partial to create the closure for partial function
application for the arguments you want.

And yes, Jack, you can check it in yourself once the initial big
problems with the PEP have been addressed.

-Brett


More information about the Python-3000 mailing list