Mangle function name with decorator?

Aaron Brady castironpi at gmail.com
Tue Mar 17 19:45:37 CET 2009


at bottom
On Mar 17, 12:54 pm, "andrew cooke" <and... at acooke.org> wrote:
> ah, ok.  then yes, you can do that with decorators.  you'd need hash
> tables or something similar in a metaclass.  then the decorator would take
> the given function, stick it in the appropriate hash table, and return a
> function that does the dispatch (ie at run time does the lookup from the
> hash table) (you'd only want to set the function once once, so it would
> need to check the function wasn't already defined).  also, the decorator
> would have one name and get/post etc would be an argument.
>
> this is all documented in the docs and peps, although it's very spread
> around.  you might look at the code for the property decorator - it's not
> doing what you want, but it's an interesting non-trivial example that's
> public.
>
> http://docs.python.org/library/functions.html#property
>
> andrew
>
> Adam wrote:
> > Thanks, Andrew.  I'm trying to accomplish something with a
> > metaprogramming flavor, where, for the convenience of the programmer
> > and the clarity of code, I'd like to have a decorator or some other
> > mechanism do twiddling behind the scenes to make a class do something
> > it wouldn't normally do.
>
> > Here's a less-obfuscated exmaple:  I want to build a framework for
> > creating MVC web applications in Python (I know, I know, there's
> > already 2^1bazillion of them) where a controller class can have
> > methods that respond to the same action but for different HTTP verbs:
snip

I didn't study the OP post very well.

It almost sounds like you want two separate classes, one with methods
for one 'state' the other with methods for another state.  You can
assign to 'self.__class__' to transition between them.

Otherwise, if you're using a hash table, the keys could be
( method_name, flag_value ) pairs, so that looking up a method with a
flag is 'meth= self._dispatch[ ( method_name, flag_value ) ]'.
However, without metaclasses or a global variable, there's no way to
remember a prior definition when you redefine a name.

class X:
  @stateA
  def M.
  @stateB
  def M.

When 'stateB( M )' is called, the result is assigned to 'M'.  There's
no way to access previous definitions of M, since there is no way to
reference the namespace that is under construction.

However, if you're willing to tolerate a little redundancy, you can
chain prior definitions of a variable onto later ones.

>>> def dec( var ):
...     def inner( fun ):
...             fun.prior= var
...             return fun
...     return inner
...
>>> class X:
...     def M( self ): pass
...     @dec( M )
...     def M( self ): pass
...
>>> X.M.prior
<function M at 0x00BA3270>
>>> X.M
<function M at 0x00BA3300>
>>>

So, you still have the earlier definition of M.  You just had to
mention it when you redefined the variable.

(Perhaps someday, we will be able to write:
def dec( namespace ):
  def outer( fun ):
    if fun.__name__ in namespace:
      namespace[ dup_var ]= namespace[ fun.__name__ ]
    return fun
  return outer
It allows us to see if there's a prior entry in the current namespace,
and save it to a different name.)



More information about the Python-list mailing list