On Mar 18, 8:47 am, Adam <adam.crossl...@gmail.com> wrote: > On Mar 17, 1:49 pm, Aaron Brady <castiro...@gmail.com> wrote: > > > > > You would need a unique attribute to look for on values in the > > dictionary, which means you'd need to detect what functions you are > > renaming; possibly by using a decorator to mark them. (Untested:) > > > class X( metaclass= M ): > > @mark( 'A' ) > > def foo( ... ). > > > class M( type ): > > def __new__( cls, name, bases, namespace ): > > for k, v in namespace.items(): > > if v.tag== 'mark-A': > > namespace[ k ]= modification( v ) > > or in your case: > > del namespace[ k ] > > namespace[ k_mod ]= v.original > > > possibly also setting func_name as well. > > return type( name, bases, namespace ) > > I tried this, but unfortunately, it still doesn't allow me to have two > methods that initially have the same name, because the namespace > dictionary that the metaclass gets only has one one entry, the last > one in. So, if I try code like this: snip
> The first definition of foo (the one that is not decorated) is over- > written by the second one, and the metaclass never sees it. Michele presented a solution to this if you are able to use Python 3. > So, I > think that I understand what you said about storing the functions in a > hashtable. That makes sense, as I can keep a reference to the > function even if ti gets over-written in the class main namespace > dictionary. However, I'm not entirely sure about how to do that with > decorators. Here is a possiblity. It's redundant, but it works. >>> class X: ... funcs= {} ... def wrap( funcs ): ... def inner( fun ): ... if fun.__name__ not in funcs: ... funcs[ fun.__name__ ]= [] ... funcs[ fun.__name__ ].append( fun ) ... return inner ... @wrap( funcs ) ... def foo( self ): pass ... @wrap( funcs ) ... def foo( self ): pass ... >>> X.funcs {'foo': [<function foo at 0x00BA32B8>, <function foo at 0x00BA3300>]} > Wouldn't the decorator function have to be bound to a > context to keep a hastable between calls? I can't us a bound method > as a decorator, can I? 'wrap' needs a reference to the hash table. I passed it explicitly, but more subtle methods might be possible. For creating the final version of 'foo' that is externally visible, you can (I presume) just access the hash table as an attribute of the class/object it's called on. Or you could set it to a generic dispatcher. The two versions are defined and called by the same name, but stored as different names. Abstractly, function overloading is a weakness of dynamic typing and variable argument lists. In order for them to be compatible, there needs to be an order of precedence, and a way to specify argument types. Decorators and annotations are two solutions. @typed( FooA ) def jam( arg1 ). @typed( FooB ) def jam( arg2 ). @typed( ) def jam( *args ). If 'jam' is called with a FooA, the first 'jam' is called. If called with a FooB, the second is. If called with any other single parameter, /or/ multiple parameters, the third is. It's unlikely you need the full range of "motion" of generic overloading, especially including variable-length and keyword argument lists, so you can probably settle for simpler. There are a couple of existing solutions out there, such as multi-methods. http://www.artima.com/weblogs/viewpost.jsp?thread=155514 IMO, defining methods under different names isn't awful. You want to call them by the same name. (Untested.) class X: def foo( self, arg ): if isinstance( arg, JamA ): self.foo_jamA( arg ) if isinstance( arg, JamB ): self.foo.jamB( arg ) #exception def foo_jamA. def foo_jamB. So here's a possibility, and you can probably make 'foo' slightly more generic. Some solutions mix the /name/ of the type into the name of the method automatically. def foo( self, arg ): getattr( self, 'foo_'+ type( arg ).__name__ )( arg ) So far, I have liked the metaclass __setattr__ and the definition chaining ideas the best. However, if you're passing the prior definition to the wrapper to chain with, it might be simpler to pass a hash table. If you subclass the class that contains the hash table, you can continue to access it: class X: funcs= {} @wrap( funcs ) def foo( self ): pass class Y( X ): @X.wrap( X.funcs ) def foo( self ): pass -- http://mail.python.org/mailman/listinfo/python-list