python - Hinzufügen einer Methode zu einer vorhandenen Objektinstanz

Translate

Ich habe gelesen, dass es möglich ist, einem vorhandenen Objekt (dh nicht in der Klassendefinition) in Python eine Methode hinzuzufügen.

Ich verstehe, dass es nicht immer gut ist, dies zu tun. Aber wie könnte man das machen?

This question and all comments follow the "Attribution Required."

Alle Antworten

Translate

In Python gibt es einen Unterschied zwischen Funktionen und gebundenen Methoden.

>>> def foo():
...     print "foo"
...
>>> class A:
...     def bar( self ):
...         print "bar"
...
>>> a = A()
>>> foo
<function foo at 0x00A98D70>
>>> a.bar
<bound method A.bar of <__main__.A instance at 0x00A9BC88>>
>>>

Gebundene Methoden wurden an eine Instanz "gebunden" (wie beschreibend), und diese Instanz wird bei jedem Aufruf der Methode als erstes Argument übergeben.

Callables, die Attribute einer Klasse sind (im Gegensatz zu einer Instanz), sind jedoch noch nicht gebunden, sodass Sie die Klassendefinition jederzeit ändern können:

>>> def fooFighters( self ):
...     print "fooFighters"
...
>>> A.fooFighters = fooFighters
>>> a2 = A()
>>> a2.fooFighters
<bound method A.fooFighters of <__main__.A instance at 0x00A9BEB8>>
>>> a2.fooFighters()
fooFighters

Zuvor definierte Instanzen werden ebenfalls aktualisiert (sofern sie das Attribut selbst nicht überschrieben haben):

>>> a.fooFighters()
fooFighters

Das Problem tritt auf, wenn Sie eine Methode an eine einzelne Instanz anhängen möchten:

>>> def barFighters( self ):
...     print "barFighters"
...
>>> a.barFighters = barFighters
>>> a.barFighters()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: barFighters() takes exactly 1 argument (0 given)

Die Funktion wird nicht automatisch gebunden, wenn sie direkt an eine Instanz angehängt wird:

>>> a.barFighters
<function barFighters at 0x00A98EF0>

Um es zu binden, können wir das verwendenMethodType-Funktion im Typmodul:

>>> import types
>>> a.barFighters = types.MethodType( barFighters, a )
>>> a.barFighters
<bound method ?.barFighters of <__main__.A instance at 0x00A9BC88>>
>>> a.barFighters()
barFighters

Diesmal waren andere Instanzen der Klasse nicht betroffen:

>>> a2.barFighters()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: A instance has no attribute 'barFighters'

Weitere Informationen finden Sie unterDeskriptorenundMetaklasse Programmierung.

Quelle
Translate

ModulNeuist seit Python 2.6 veraltet und in 3.0 entfernt, verwendenTypen

sehenhttp://docs.python.org/library/new.html

Im folgenden Beispiel habe ich den Rückgabewert absichtlich entferntpatch_me()Funktion. Ich denke, dass das Geben des Rückgabewerts einen glauben lässt, dass der Patch ein neues Objekt zurückgibt, was nicht wahr ist - es modifiziert das eingehende. Wahrscheinlich kann dies einen disziplinierteren Einsatz von Monkeypatching ermöglichen.

import types

class A(object):#but seems to work for old style objects too
    pass

def patch_me(target):
    def method(target,x):
        print "x=",x
        print "called from", target
    target.method = types.MethodType(method,target)
    #add more if needed

a = A()
print a
#out: <__main__.A object at 0x2b73ac88bfd0>  
patch_me(a)    #patch instance
a.method(5)
#out: x= 5
#out: called from <__main__.A object at 0x2b73ac88bfd0>
patch_me(A)
A.method(6)        #can patch class too
#out: x= 6
#out: called from <class '__main__.A'>
Quelle
Translate

Vorwort - ein Hinweis zur Kompatibilität: Andere Antworten funktionieren möglicherweise nur in Python 2 - diese Antwort sollte in Python 2 und 3 einwandfrei funktionieren. Wenn Sie nur Python 3 schreiben, können Sie das explizite Erben von auslassenobject, aber sonst sollte der Code gleich bleiben.

Hinzufügen einer Methode zu einer vorhandenen Objektinstanz

Ich habe gelesen, dass es möglich ist, einem vorhandenen Objekt (z. B. nicht in der Klassendefinition) in Python eine Methode hinzuzufügen.

Ich verstehe, dass es nicht immer eine gute Entscheidung ist, dies zu tun.Aber wie könnte man das machen?

Ja, es ist möglich - aber nicht zu empfehlen

Ich empfehle das nicht. Das ist eine schlechte Idee. Tu es nicht.

Hier sind einige Gründe:

  • Sie fügen jeder Instanz, für die Sie dies tun, ein gebundenes Objekt hinzu. Wenn Sie dies häufig tun, verschwenden Sie wahrscheinlich viel Speicher. Gebundene Methoden werden normalerweise nur für die kurze Dauer ihres Aufrufs erstellt und existieren dann nicht mehr, wenn automatisch Müll gesammelt wird. Wenn Sie dies manuell tun, erhalten Sie eine Namensbindung, die auf die gebundene Methode verweist. Dadurch wird die Speicherbereinigung bei Verwendung verhindert.
  • Objektinstanzen eines bestimmten Typs haben im Allgemeinen ihre Methoden für alle Objekte dieses Typs. Wenn Sie an anderer Stelle Methoden hinzufügen, verfügen einige Instanzen über diese Methoden, andere nicht. Programmierer werden dies nicht erwarten, und Sie riskieren eine Verletzung derRegel der geringsten Überraschung.
  • Da es andere wirklich gute Gründe gibt, dies nicht zu tun, geben Sie sich zusätzlich einen schlechten Ruf, wenn Sie dies tun.

Daher schlage ich vor, dass Sie dies nur tun, wenn Sie einen wirklich guten Grund haben.Es ist weitaus besser, die richtige Methode in der Klassendefinition zu definierenoderwenigervorzugsweise, um die Klasse direkt wie folgt zu patchen:

Foo.sample_method = sample_method

Da es jedoch lehrreich ist, werde ich Ihnen einige Möglichkeiten zeigen, dies zu tun.

Wie es geht

Hier ist ein Setup-Code. Wir brauchen eine Klassendefinition. Es könnte importiert werden, aber es spielt wirklich keine Rolle.

class Foo(object):
    '''An empty class to demonstrate adding a method to an instance'''

Erstellen Sie eine Instanz:

foo = Foo()

Erstellen Sie eine Methode, um sie hinzuzufügen:

def sample_method(self, bar, baz):
    print(bar + baz)

Methode nichts (0) - benutze die Deskriptormethode,__get__

Gepunktete Suchvorgänge für Funktionen rufen die auf__get__Methode der Funktion mit der Instanz, die das Objekt an die Methode bindet und so eine "gebundene Methode" erstellt.

foo.sample_method = sample_method.__get__(foo)

und nun:

>>> foo.sample_method(1,2)
3

Methode eins - types.MethodType

Importieren Sie zunächst die Typen, von denen wir den Methodenkonstruktor erhalten:

import types

Jetzt fügen wir die Methode der Instanz hinzu. Dazu benötigen wir den MethodType-Konstruktor aus demtypesModul (das wir oben importiert haben).

Die Argument-Signatur für types.MethodType lautet(function, instance, class):

foo.sample_method = types.MethodType(sample_method, foo, Foo)

und Verwendung:

>>> foo.sample_method(1,2)
3

Methode zwei: lexikalische Bindung

Zuerst erstellen wir eine Wrapper-Funktion, die die Methode an die Instanz bindet:

def bind(instance, method):
    def binding_scope_fn(*args, **kwargs): 
        return method(instance, *args, **kwargs)
    return binding_scope_fn

Verwendung:

>>> foo.sample_method = bind(foo, sample_method)    
>>> foo.sample_method(1,2)
3

Methode drei: functools.partial

Eine Teilfunktion wendet die ersten Argumente auf eine Funktion (und optional auf Schlüsselwortargumente) an und kann später mit den verbleibenden Argumenten (und überschreibenden Schlüsselwortargumenten) aufgerufen werden. So:

>>> from functools import partial
>>> foo.sample_method = partial(sample_method, foo)
>>> foo.sample_method(1,2)
3    

Dies ist sinnvoll, wenn Sie bedenken, dass gebundene Methoden Teilfunktionen der Instanz sind.

Ungebundene Funktion als Objektattribut - warum das nicht funktioniert:

Wenn wir versuchen, die sample_method auf die gleiche Weise hinzuzufügen, wie wir sie möglicherweise zur Klasse hinzufügen, ist sie nicht an die Instanz gebunden und nimmt das implizite Selbst nicht als erstes Argument.

>>> foo.sample_method = sample_method
>>> foo.sample_method(1,2)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: sample_method() takes exactly 3 arguments (2 given)

Wir können die ungebundene Funktion zum Funktionieren bringen, indem wir die Instanz explizit übergeben (oder irgendetwas anderes, da diese Methode die nicht wirklich verwendetselfArgumentvariable), aber es würde nicht mit der erwarteten Signatur anderer Instanzen übereinstimmen (wenn wir diese Instanz mit Affen patchen):

>>> foo.sample_method(foo, 1, 2)
3

Fazit

Sie kennen jetzt mehrere MöglichkeitenkönntenTu das, aber im Ernst - tu das nicht.

Quelle
Translate

Ich denke, dass die obigen Antworten den entscheidenden Punkt verfehlt haben.

Lassen Sie uns eine Klasse mit einer Methode haben:

class A(object):
    def m(self):
        pass

Lassen Sie uns jetzt in ipython damit spielen:

In [2]: A.m
Out[2]: <unbound method A.m>

OK, alsom ()irgendwie wird eine ungebundene Methode vonA. Aber ist es wirklich so?

In [5]: A.__dict__['m']
Out[5]: <function m at 0xa66b8b4>

Es stellt sich heraus, dassm ()ist nur eine Funktion, zu der ein Verweis hinzugefügt wirdAKlassenwörterbuch - es gibt keine Magie. Warum dannAmgibt uns eine ungebundene Methode? Dies liegt daran, dass der Punkt nicht in eine einfache Wörterbuchsuche übersetzt wird. Es ist de facto ein Aufruf von A .__ Klasse __.__ getattribute __ (A, 'm'):

In [11]: class MetaA(type):
   ....:     def __getattribute__(self, attr_name):
   ....:         print str(self), '-', attr_name

In [12]: class A(object):
   ....:     __metaclass__ = MetaA

In [23]: A.m
<class '__main__.A'> - m
<class '__main__.A'> - m

Jetzt bin ich mir nicht sicher, warum die letzte Zeile zweimal gedruckt wird, aber es ist immer noch klar, was dort vor sich geht.

Das Standard-__getattribute__ überprüft nun, ob es sich bei dem Attribut um ein sogenanntes Attribut handeltDeskriptoroder nicht, dh wenn eine spezielle __get__ -Methode implementiert wird. Wenn diese Methode implementiert wird, wird das Ergebnis des Aufrufs dieser __get__ -Methode zurückgegeben. Zurück zur ersten Version unsererAKlasse, das ist was wir haben:

In [28]: A.__dict__['m'].__get__(None, A)
Out[28]: <unbound method A.m>

Und da Python-Funktionen das Deskriptorprotokoll implementieren, binden sie sich in ihrer __get__ -Methode an dieses Objekt, wenn sie im Namen eines Objekts aufgerufen werden.

Ok, wie fügt man einem vorhandenen Objekt eine Methode hinzu? Angenommen, es macht Ihnen nichts aus, die Klasse zu patchen, ist es so einfach wie:

B.m = m

DannBm"wird" dank der Deskriptormagie zu einer ungebundenen Methode.

Wenn Sie eine Methode nur einem einzelnen Objekt hinzufügen möchten, müssen Sie die Maschinerie mithilfe von types selbst emulieren. MethodType:

b.m = types.MethodType(m, b)

Apropos:

In [2]: A.m
Out[2]: <unbound method A.m>

In [59]: type(A.m)
Out[59]: <type 'instancemethod'>

In [60]: type(b.m)
Out[60]: <type 'instancemethod'>

In [61]: types.MethodType
Out[61]: <type 'instancemethod'>
Quelle
Translate

In Python funktioniert das Patchen von Affen im Allgemeinen durch Überschreiben einer Klassen- oder Funktionssignatur mit Ihrer eigenen. Unten ist ein Beispiel aus demZope Wiki:

from SomeOtherProduct.SomeModule import SomeClass
def speak(self):
   return "ook ook eee eee eee!"
SomeClass.speak = speak

Dieser Code überschreibt / erstellt eine Methode namens speak für die Klasse. In Jeff Atwoodsletzter Beitrag über das Patchen von Affen. Er zeigt ein Beispiel in C # 3.0, der aktuellen Sprache, die ich für die Arbeit verwende.

Quelle
Translate

Sie können Lambda verwenden, um eine Methode an eine Instanz zu binden:

def run(self):
    print self._instanceString

class A(object):
    def __init__(self):
        self._instanceString = "This is instance string"

a = A()
a.run = lambda: run(a)
a.run()

Ausgabe:

This is instance string
Quelle
Translate

Es gibt mindestens zwei Möglichkeiten, eine Methode an eine Instanz ohne anzuhängentypes.MethodType:

>>> class A:
...  def m(self):
...   print 'im m, invoked with: ', self

>>> a = A()
>>> a.m()
im m, invoked with:  <__main__.A instance at 0x973ec6c>
>>> a.m
<bound method A.m of <__main__.A instance at 0x973ec6c>>
>>> 
>>> def foo(firstargument):
...  print 'im foo, invoked with: ', firstargument

>>> foo
<function foo at 0x978548c>

1:

>>> a.foo = foo.__get__(a, A) # or foo.__get__(a, type(a))
>>> a.foo()
im foo, invoked with:  <__main__.A instance at 0x973ec6c>
>>> a.foo
<bound method A.foo of <__main__.A instance at 0x973ec6c>>

2:

>>> instancemethod = type(A.m)
>>> instancemethod
<type 'instancemethod'>
>>> a.foo2 = instancemethod(foo, a, type(a))
>>> a.foo2()
im foo, invoked with:  <__main__.A instance at 0x973ec6c>
>>> a.foo2
<bound method instance.foo of <__main__.A instance at 0x973ec6c>>

Nützliche Links:
Datenmodell - Aufrufen von Deskriptoren
Descriptor HowTo Guide - Aufrufen von Deskriptoren

Quelle
HS.
Translate

Was Sie suchen, istsetattrIch glaube. Verwenden Sie diese Option, um ein Attribut für ein Objekt festzulegen.

>>> def printme(s): print repr(s)
>>> class A: pass
>>> setattr(A,'printme',printme)
>>> a = A()
>>> a.printme() # s becomes the implicit 'self' variable
< __ main __ . A instance at 0xABCDEFG>
Quelle
Translate

Da diese Frage für Nicht-Python-Versionen gestellt wurde, ist hier JavaScript:

a.methodname = function () { console.log("Yay, a new method!") }
Quelle
Translate

Konsolidierung der Antworten von Jason Pratt und des Community-Wikis mit Blick auf die Ergebnisse verschiedener Bindungsmethoden:

Beachten Sie insbesondere, wie die Bindungsfunktion als Klassenmethode hinzugefügt wirdfunktioniert, aber der Referenzierungsbereich ist falsch.

#!/usr/bin/python -u
import types
import inspect

## dynamically adding methods to a unique instance of a class


# get a list of a class's method type attributes
def listattr(c):
    for m in [(n, v) for n, v in inspect.getmembers(c, inspect.ismethod) if isinstance(v,types.MethodType)]:
        print m[0], m[1]

# externally bind a function as a method of an instance of a class
def ADDMETHOD(c, method, name):
    c.__dict__[name] = types.MethodType(method, c)

class C():
    r = 10 # class attribute variable to test bound scope

    def __init__(self):
        pass

    #internally bind a function as a method of self's class -- note that this one has issues!
    def addmethod(self, method, name):
        self.__dict__[name] = types.MethodType( method, self.__class__ )

    # predfined function to compare with
    def f0(self, x):
        print 'f0\tx = %d\tr = %d' % ( x, self.r)

a = C() # created before modified instnace
b = C() # modified instnace


def f1(self, x): # bind internally
    print 'f1\tx = %d\tr = %d' % ( x, self.r )
def f2( self, x): # add to class instance's .__dict__ as method type
    print 'f2\tx = %d\tr = %d' % ( x, self.r )
def f3( self, x): # assign to class as method type
    print 'f3\tx = %d\tr = %d' % ( x, self.r )
def f4( self, x): # add to class instance's .__dict__ using a general function
    print 'f4\tx = %d\tr = %d' % ( x, self.r )


b.addmethod(f1, 'f1')
b.__dict__['f2'] = types.MethodType( f2, b)
b.f3 = types.MethodType( f3, b)
ADDMETHOD(b, f4, 'f4')


b.f0(0) # OUT: f0   x = 0   r = 10
b.f1(1) # OUT: f1   x = 1   r = 10
b.f2(2) # OUT: f2   x = 2   r = 10
b.f3(3) # OUT: f3   x = 3   r = 10
b.f4(4) # OUT: f4   x = 4   r = 10


k = 2
print 'changing b.r from {0} to {1}'.format(b.r, k)
b.r = k
print 'new b.r = {0}'.format(b.r)

b.f0(0) # OUT: f0   x = 0   r = 2
b.f1(1) # OUT: f1   x = 1   r = 10  !!!!!!!!!
b.f2(2) # OUT: f2   x = 2   r = 2
b.f3(3) # OUT: f3   x = 3   r = 2
b.f4(4) # OUT: f4   x = 4   r = 2

c = C() # created after modifying instance

# let's have a look at each instance's method type attributes
print '\nattributes of a:'
listattr(a)
# OUT:
# attributes of a:
# __init__ <bound method C.__init__ of <__main__.C instance at 0x000000000230FD88>>
# addmethod <bound method C.addmethod of <__main__.C instance at 0x000000000230FD88>>
# f0 <bound method C.f0 of <__main__.C instance at 0x000000000230FD88>>

print '\nattributes of b:'
listattr(b)
# OUT:
# attributes of b:
# __init__ <bound method C.__init__ of <__main__.C instance at 0x000000000230FE08>>
# addmethod <bound method C.addmethod of <__main__.C instance at 0x000000000230FE08>>
# f0 <bound method C.f0 of <__main__.C instance at 0x000000000230FE08>>
# f1 <bound method ?.f1 of <class __main__.C at 0x000000000237AB28>>
# f2 <bound method ?.f2 of <__main__.C instance at 0x000000000230FE08>>
# f3 <bound method ?.f3 of <__main__.C instance at 0x000000000230FE08>>
# f4 <bound method ?.f4 of <__main__.C instance at 0x000000000230FE08>>

print '\nattributes of c:'
listattr(c)
# OUT:
# attributes of c:
# __init__ <bound method C.__init__ of <__main__.C instance at 0x0000000002313108>>
# addmethod <bound method C.addmethod of <__main__.C instance at 0x0000000002313108>>
# f0 <bound method C.f0 of <__main__.C instance at 0x0000000002313108>>

Persönlich bevorzuge ich die externe ADDMETHOD-Funktionsroute, da ich damit auch innerhalb eines Iterators dynamisch neue Methodennamen zuweisen kann.

def y(self, x):
    pass
d = C()
for i in range(1,5):
    ADDMETHOD(d, y, 'f%d' % i)
print '\nattributes of d:'
listattr(d)
# OUT:
# attributes of d:
# __init__ <bound method C.__init__ of <__main__.C instance at 0x0000000002303508>>
# addmethod <bound method C.addmethod of <__main__.C instance at 0x0000000002303508>>
# f0 <bound method C.f0 of <__main__.C instance at 0x0000000002303508>>
# f1 <bound method ?.y of <__main__.C instance at 0x0000000002303508>>
# f2 <bound method ?.y of <__main__.C instance at 0x0000000002303508>>
# f3 <bound method ?.y of <__main__.C instance at 0x0000000002303508>>
# f4 <bound method ?.y of <__main__.C instance at 0x0000000002303508>>
Quelle
Max
Translate

Dies ist eigentlich ein Addon zur Antwort von "Jason Pratt"

Obwohl Jasons Antwort funktioniert, funktioniert es nur, wenn man einer Klasse eine Funktion hinzufügen möchte. Es hat bei mir nicht funktioniert, als ich versucht habe, eine bereits vorhandene Methode aus der .py-Quellcodedatei neu zu laden.

Ich habe ewig gebraucht, um eine Problemumgehung zu finden, aber der Trick scheint einfach zu sein ... 1. Importieren Sie den Code aus der Quellcodedatei 2. Erzwingen Sie ein erneutes Laden 3. Verwenden Sie types.FunctionType (...), um die zu konvertieren importierte und gebundene Methode an eine Funktion Sie können auch die aktuellen globalen Variablen weitergeben, da sich die neu geladene Methode in einem anderen Namespace befindet. 4. Jetzt können Sie wie von "Jason Pratt" vorgeschlagen mit den types.MethodType (... )

Beispiel:

# this class resides inside ReloadCodeDemo.py
class A:
    def bar( self ):
        print "bar1"

    def reloadCode(self, methodName):
        ''' use this function to reload any function of class A'''
        import types
        import ReloadCodeDemo as ReloadMod # import the code as module
        reload (ReloadMod) # force a reload of the module
        myM = getattr(ReloadMod.A,methodName) #get reloaded Method
        myTempFunc = types.FunctionType(# convert the method to a simple function
                                myM.im_func.func_code, #the methods code
                                globals(), # globals to use
                                argdefs=myM.im_func.func_defaults # default values for variables if any
                                ) 
        myNewM = types.MethodType(myTempFunc,self,self.__class__) #convert the function to a method
        setattr(self,methodName,myNewM) # add the method to the function

if __name__ == '__main__':
    a = A()
    a.bar()
    # now change your code and save the file
    a.reloadCode('bar') # reloads the file
    a.bar() # now executes the reloaded code
Quelle
Translate

Wenn es hilfreich sein kann, habe ich kürzlich eine Python-Bibliothek namens Gorilla veröffentlicht, um das Patchen von Affen bequemer zu gestalten.

Verwenden einer Funktionneedle()um ein Modul mit dem Namen zu patchenguineapiggeht wie folgt:

import gorilla
import guineapig
@gorilla.patch(guineapig)
def needle():
    print("awesome")

Es kümmert sich aber auch um interessantere Anwendungsfälle, wie in derFAQvon demDokumentation.

Der Code ist verfügbar amGitHub.

Quelle
Translate

Was Jason Pratt gepostet hat, ist richtig.

>>> class Test(object):
...   def a(self):
...     pass
... 
>>> def b(self):
...   pass
... 
>>> Test.b = b
>>> type(b)
<type 'function'>
>>> type(Test.a)
<type 'instancemethod'>
>>> type(Test.b)
<type 'instancemethod'>

Wie Sie sehen können, betrachtet Python b () nicht anders als a (). In Python sind alle Methoden nur Variablen, die zufällig Funktionen sind.

Quelle
Translate

Diese Frage wurde vor Jahren gestellt, aber es gibt eine einfache Möglichkeit, die Bindung einer Funktion an eine Klasseninstanz mithilfe von Dekoratoren zu simulieren:

def binder (function, instance):
  copy_of_function = type (function) (function.func_code, {})
  copy_of_function.__bind_to__ = instance
  def bound_function (*args, **kwargs):
    return copy_of_function (copy_of_function.__bind_to__, *args, **kwargs)
  return bound_function


class SupaClass (object):
  def __init__ (self):
    self.supaAttribute = 42


def new_method (self):
  print self.supaAttribute


supaInstance = SupaClass ()
supaInstance.supMethod = binder (new_method, supaInstance)

otherInstance = SupaClass ()
otherInstance.supaAttribute = 72
otherInstance.supMethod = binder (new_method, otherInstance)

otherInstance.supMethod ()
supaInstance.supMethod ()

Wenn Sie dort die Funktion und die Instanz an den Ordnerdekorateur übergeben, wird dort eine neue Funktion mit demselben Codeobjekt wie das erste erstellt. Anschließend wird die angegebene Instanz der Klasse in einem Attribut der neu erstellten Funktion gespeichert. Der Dekorateur gibt eine (dritte) Funktion zurück, die automatisch die kopierte Funktion aufruft und die Instanz als ersten Parameter angibt.

Abschließend erhalten Sie eine Funktion, die simuliert, dass sie an die Klasseninstanz gebunden ist. Die ursprüngliche Funktion bleibt unverändert.

Quelle
Translate

Ich finde es seltsam, dass niemand erwähnt hat, dass alle oben aufgeführten Methoden eine Zyklusreferenz zwischen der hinzugefügten Methode und der Instanz erstellen, wodurch das Objekt bis zur Speicherbereinigung persistent bleibt. Es gab einen alten Trick beim Hinzufügen eines Deskriptors durch Erweitern der Klasse des Objekts:

def addmethod(obj, name, func):
    klass = obj.__class__
    subclass = type(klass.__name__, (klass,), {})
    setattr(subclass, name, func)
    obj.__class__ = subclass
Quelle
Translate
from types import MethodType

def method(self):
   print 'hi!'


setattr( targetObj, method.__name__, MethodType(method, targetObj, type(method)) )

Hiermit können Sie den Selbstzeiger verwenden

Quelle