2014-04-05 10 views
6

Ich habe einen Hintergrund in Python (obwohl völlig autodidaktisch, so dass ich einige schlechte Angewohnheiten oder Missverständnisse haben könnte), und ich versuche Ruby zu lernen, um meinen Umfang zu erweitern.Metaprogrammierung in Python - Hinzufügen einer Objektmethode

Ich las einige Vergleiche durch und sah viele Behauptungen, dass "Python keine Metaprogrammierung machen kann" (oder, weniger inflammatorisch, "Python kann Metaprogrammierung nicht so einfach wie Ruby machen"). Ich ging also weg und las schnell über Metaprogrammierung und kam mit dem Eindruck, dass es im Grunde die Methoden/das Verhalten Ihrer Klassen/Objekte zur Laufzeit editiert (bitte korrigiert mich, wenn ich falsch bin!).

Ich hatte den Eindruck, dass, da Python dynamisch ist, dass das kein Problem sein sollte. Allerdings lief ich den folgenden Testcode, der nicht die Antwort geben habe ich erwartet:

>>> class foo: 
...  def make_hello_method(self): 
...    def hello(obj): 
...      print 'hello' 
...    self.hello = hello 
... 
>>> f = foo() 
>>> f.hello() 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
AttributeError: foo instance has no attribute 'hello' 
>>> f.make_hello_method() 
>>> f.hello() 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
TypeError: hello() takes exactly 1 argument (0 given) 

Ich hatte den Eindruck, dass jeder Methode eines Objekts automatisch das Objekt selbst als erstes Argument übergeben wurde (daher der Konstante Anforderungen zur Definition von Objektmethoden wie (self, [...])). Warum wird f nicht an hello() übergeben?

+0

Duplizieren von http://stackoverflow.com/questions/972/ Hinzufügen einer Methode zu einem bestehenden Objekt – spinlok

Antwort

5

Sie müssen es zu einer Instanzmethode machen. Im Modul types gibt es dafür eine Klasse. Dies funktioniert:

self.hello = types.MethodType(hello, self) 
+0

Ah, hab ich. Der Aufruf von type() auf 'f.make_hello_method' und auf' f.hello' machte den Unterschied deutlich. Vielen Dank! – scubbo

+0

@scubbo: Wenn Sie die Methode der Klasse und nicht nur der einen Instanz hinzufügen möchten, müssen Sie stattdessen etwas wie 'setattr (foo," hallo ", hallo)' verwenden, das es der Klasse hinzufügen würde. alle vorhandenen Instanzen sowie alle neuen Instanzen, die erstellt werden. – martineau

2

Sehen, wie Sie Python 2 verwenden, können Sie das new Modul verwenden könnte diese Arbeit zu machen:

self.hello = new.instancemethod(hello, self, foo) 
Verwandte Themen