Comment ajouter une méthode en utilisant une métaclasse
Question
Comment puis-je ajouter une méthode d'instance à une classe à l'aide d'une métaclasse (oui, il faut utiliser une métaclasse)? Le type de travail suivant fonctionne, mais le func_name sera toujours "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'
Mon problème est que certains codes de bibliothèque utilisent réellement le nom_fonction et que plus tard, la méthode 'bar' de l'instance Foo n'a pas été trouvée. Je pourrais faire:
dict["foobar"] = types.FunctionType(bar.func_code, {}, "foobar")
Il existe également des types.MethodType, mais j'ai besoin d'une instance qui n'existe pas encore pour l'utiliser. Est-ce qu'il me manque quelque chose ici?
La solution
Essayez d'étendre dynamiquement les bases de cette façon, vous pouvez tirer parti de la méthode mro et les méthodes sont des méthodes réelles:
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
Autres conseils
Je pense que ce que vous voulez faire est le suivant:
>>> 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'
Vous êtes maintenant libre de passer des Foo
à une bibliothèque qui s'attend à ce que les instances Foo
aient une méthode nommée foobar
.
Malheureusement, (1) je ne sais pas comment utiliser les métaclasses et (2) je ne suis pas sûr de lire votre question correctement, mais j'espère que cela vous aidera.
Notez que nom_fonction
est uniquement assignable dans Python 2.4 et versions ultérieures.