Metaclass conundrum - binding value from an outer scope

Skip Montanaro skip.montanaro at gmail.com
Sat Apr 22 16:16:34 EDT 2017


> Another round, this time with a metaclass. As you have found partial() does
> not work as a method because it's not a descriptor (i. e. no __get__()
> method). Instead you can try a closure:
>
> def make_method(a):
>     underlying = getattr(SomeOtherClass, a)
>     @functools.wraps(underlying)
>     def _meth(self, *args, **kw):
>         return underlying(self._instance, *args, **kw)
>     return _meth
>
> class SomeMeta(type):
>     def __new__(cls, name, parents, dct):
>         for a in dir(SomeOtherClass):
>             if a[0] == "_": continue
>             dct[a] = make_method(a)
>         return super(SomeMeta, cls).__new__(cls, name, parents, dct)

Dang, Peter... That looks like it will do exactly what I need. Here's
help on SomeOtherClass with its one method:

class SomeOtherClass(__builtin__.object)
 |  Methods defined here:
 |
 |  meth1(self)
 |      meth1 doc
 ...

And, here's SomeClass (__metaclass__ = SomeMeta), which defines meth2,
but steals meth1 from SomeOtherClass:

class SomeClass(__builtin__.object)
 |  Methods defined here:
 |
 |  meth1(self, *args, **kw)
 |      meth1 doc
 |
 |  meth2(self)
 |      meth2 doc
 ...

With a bit of introspection in make_method (or an extension of
functools.wraps), I can probably make SomeClass.meth1 have the same
signature as SomeOtherClass.meth1.

Thx,

Skip


More information about the Python-list mailing list