2017-09-25 1 views
0

J'ai un code où je veux 'voler' les méthodes d'une autre classe en cours d'exécution. (C'est un petit jeu et je veux permettre aux bots de changer de stratégie à la demande).Comment copier la méthode non-bornée en tant que borne dans une instance de classe en Python

Exemple:

class X(object): 
    def foo(self): 
     return 1 


class Y(object): 
    def foo(self): 
     return 2 

Je veux 'copie' Y.foo en instance de classe X:

x.foo = Y.foo 
x.foo() # unbound method 
x.foo = types.MethodType(Y.foo, x) 
x.foo() # TypeError: unbound method foo() must be called with Y instance as first argument (got X instance instead 
tmp=x.foo.__self__ 
x.foo=Y.foo 
x.foo.__self__ = tmp # readonly attribute 
x.foo.__func__ = Y.bar.__func__ # readonly attribute 

Est-il possible de copier fonction d'une classe dans un autre dans l'exécution, sans:

  1. Héritage (il doit être fait à l'intérieur la méthode de classe instanciée)
  2. appelant Y.bar de l'intérieur x.foo
+0

Avez-vous regardé le modèle de stratégie? –

Répondre

3

En Python 2, l'accès à une méthode de la classe renvoie un procédé non lié. déroulez simplement cette méthode pour obtenir la fonction d'origine, en utilisant l'attribut __func__:

x.foo = types.MethodType(Y.foo.__func__, x) 

Vous pourriez dire que la fonction de se lier à l'aide du descriptor protocol:

x.foo = Y.foo.__func__.__get__(x) 

Démo:

>>> class X(object): 
...  def foo(self): 
...   return 1 
... 
>>> class Y(object): 
...  def foo(self): 
...   return 2 
... 
>>> x = X() 
>>> Y.foo 
<unbound method Y.foo> 
>>> Y.foo.__func__ 
<function foo at 0x1006d1b18> 
>>> Y.foo.__func__.__get__(x) 
<bound method ?.foo of <__main__.X object at 0x1006e84d0>> 
>>> x.foo = Y.foo.__func__.__get__(x) 
>>> x.foo() 
2