Cómo agregar un método usando metaclase
Pregunta
¿Cómo agrego un método de instancia a una clase usando una metaclase (sí, necesito usar una metaclase)?El siguiente tipo de trabajo, pero func_name seguirá siendo "foo":
def bar(self):
print "bar"
class MetaFoo(type):
def __new__(cls, name, bases, dict):
dict["foobar"] = bar
return type(name, bases, dict)
class Foo(object):
__metaclass__ = MetaFoo
>>> f = Foo()
>>> f.foobar()
bar
>>> f.foobar.func_name
'bar'
Mi problema es que algún código de biblioteca en realidad usa func_name y luego no logra encontrar el método 'bar' de la instancia de Foo.Yo podría hacer:
dict["foobar"] = types.FunctionType(bar.func_code, {}, "foobar")
También hay tipos.MethodType, pero necesito una instancia que aún no existe para usarlo.¿Me estoy perdiendo algo aquí?
Solución
Intente extender dinámicamente las bases de esa manera podrá aprovechar el mro y los métodos son métodos reales:
class Parent(object):
def bar(self):
print "bar"
class MetaFoo(type):
def __new__(cls, name, bases, dict):
return type(name, (Parent,) + bases, dict)
class Foo(object):
__metaclass__ = MetaFoo
if __name__ == "__main__":
f = Foo()
f.bar()
print f.bar.func_name
Otros consejos
Creo que lo que quieres hacer es esto:
>>> class Foo():
... def __init__(self, x):
... self.x = x
...
>>> def bar(self):
... print 'bar:', self.x
...
>>> bar.func_name = 'foobar'
>>> Foo.foobar = bar
>>> f = Foo(12)
>>> f.foobar()
bar: 12
>>> f.foobar.func_name
'foobar'
Ahora eres libre de pasar Foo
s a una biblioteca que espera Foo
instancias para tener un método llamado foobar
.
Desafortunadamente, (1) no sé cómo usar metaclases y (2) no estoy seguro de haber leído tu pregunta correctamente, pero espero que esto ayude.
Tenga en cuenta que func_name
solo se puede asignar en Python 2.4 y superior.