2017-08-18 1 views
1

Si on change un attribut d'objet qui fait référence à une méthode interne à une fonction externe après la création de l'objet, self n'est pas passé à la nouvelle fonction, même si l'attribut (qui contient une fonction) est appelé comme avant.Pourquoi ne passe-t-on pas automatiquement une fois qu'un attribut est modifié pour faire référence à une fonction externe?

class Person: 
    def greet(self): 
     print("hello") 

    do = greet 

def wave(person): 
    print("bye") 

alice = Person() 
alice.do() #prints 'hello' 

#change do to point an external function 
alice.do = wave 
alice.do() #Error: Missing argument 

L'erreur exacte que je reçois est:

hello 
Traceback (most recent call last): 
    File "C:\Users\Owner\Desktop\miniLiveMethodSwitch.py", line 15, in <module> 
    alice.do() #Error: Missing argument 
TypeError: wave() missing 1 required positional argument: 'person' 

Si un mouvement de la fonction externe dans la classe comme méthode interne,

class Person: 
    def greet(self): 
     print("hello") 

    def wave(person): 
     print("bye") 

    do = greet 

Ensuite, le code fonctionne comme prévu. Pourquoi n'est-il pas passé automatiquement une fois que l'attribut est modifié pour faire référence à une fonction externe? Quelle est la bonne façon d'appeler la fonction afin que le soi soit passé?

Répondre

4

Lorsque Python trouve alice.do dans le dict de classe, il invoque la descriptor protocol, appelant __get__ de la fonction méthode produire un objet de méthode liée qui sera le résultat de la recherche alice.do. Cet objet de méthode liée sait ce que doit être self et insère automatiquement l'argument self dans la liste d'arguments lors de la transmission d'arguments à la fonction sous-jacente. (Cela se produit positionnelle, non pas par le nom self.)

Lorsque Python trouve par exemple de » alice.do dans alice dict, le protocole descripteur n'est pas invoqué, et alice.do est juste la fonction première. self n'est pas injecté.

0

Essayez ceci:

class Person: 
    def greet(self): 
     print("hello") 

    do = greet 

def wave(person): 
    print("bye") 

alice = Person() 
alice.do() #prints 'hello' 
print(type(alice.do)) 

#change do to point an external function 
alice.do = wave 
print(type(alice.do)) 

La sortie est: method puis function:

hello 
<class 'method'> 
<class 'function'>