Vă mulțumim pentru susținere

Adăugarea unei metode la o instanță a unui obiect existent

Am citit că este posibil să adăugați o metodă la un obiect existent (adică nu la definiția clasei) în Python.

Înțeleg că nu este întotdeauna bine să faceți acest lucru. Dar cum ar putea face asta?

0
adăugat editat

18 răspunsuri

Nu cunosc sintaxa Python, dar știu că Ruby o poate face și este destul de banală. Să presupunem că doriți să adăugați o metodă în Array care imprimă lungimea la standard:

class Array
  def print_length
    puts length
  end
end

Dacă nu doriți să modificați întreaga clasă, puteți să adăugați metoda într-o singură instanță a matricei și nici o altă matrice nu va avea metoda:

array = [1, 2, 3]
def array.print_length
  puts length
end

Trebuie doar să fii conștient de problemele implicate în utilizarea acestei funcții. Jeff Atwood de fapt, a scris despre el nu cu mult timp în urmă.

0
adăugat

Ceea ce căutați este setattr cred. Utilizați această opțiune pentru a seta un atribut pe un obiect.

>>> 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>
0
adăugat
Există un motiv să utilizați setattr (A, 'printme', printme) în loc de pur și simplu A.printme = printme ?
adăugat autor Tobias Kienzler
Aceasta este patch-ul A , nu instanța a .
adăugat autor Ethan Furman
Are sens dacă se construiește numele metodei în timpul rulării.
adăugat autor rr-

Adăugarea unei metode la o instanță a unui obiect existent

     

Am citit că este posibil să adăugați o metodă la un obiect existent (de exemplu, nu în definiția clasei) în Python.

     

Înțeleg că nu este întotdeauna o decizie bună de a face acest lucru. Dar cum se poate face acest lucru?

Da, este posibil - Dar nu este recomandat

Nu recomand acest lucru. Aceasta este o idee rea. Nu face asta.

Iată câteva motive:

  • Veți adăuga un obiect legat la fiecare instanță în care faceți acest lucru. Dacă faceți acest lucru mult, veți pierde o mulțime de memorie. Metodele legate sunt, de obicei, create numai pentru durata scurtă a apelului lor și apoi încetează să mai existe atunci când se colectează gunoi automat. Dacă faceți acest lucru manual, veți avea un nume obligatoriu referindu-se la metoda legată - care va împiedica colectarea gunoiului în timpul utilizării.
  • Exemplele de obiecte dintr-un anumit tip au în general metode pentru toate obiectele de acel tip. Dacă adăugați metode în altă parte, unele cazuri vor avea acele metode, iar altele nu vor. Programatorii nu se vor aștepta la acest lucru și riscați să încalci regula cu cea mai mică surpriză .
  • Deoarece există și alte motive foarte bune pentru a nu face acest lucru, vă veți da și o reputație proastă dacă o faceți.

Astfel, vă sugerez să nu faceți acest lucru dacă nu aveți un motiv foarte bun. Este mult mai bine să definiți metoda corectă în definirea clasei sau mai puțin , de preferință pentru a repara direct clasa de maimuță, astfel:

Foo.sample_method = sample_method

Din moment ce este instructiv, totuși, vă voi arăta câteva modalități de a face acest lucru.

Cum se poate face

Iată câteva coduri de configurare. Avem nevoie de o definiție a clasei. Ar putea fi importat, dar nu contează.

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

Creați o instanță:

foo = Foo()

Creați o metodă de adăugat la ea:

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

Method nought (0) - use the descriptor method, __get__

Căutările punctate pe funcții apelează metoda __ get __ a funcției cu instanța, legând obiectul la metodă și creând astfel o "metodă legată".

foo.sample_method = sample_method.__get__(foo)

si acum:

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

Metoda One - types.MethodType

Mai întâi, tipurile de importuri, de la care vom obține constructorul de metode:

import types

Acum adăugăm metoda la instanță. Pentru a face acest lucru, avem nevoie de constructorul MethodType din modulul types (pe care l-am importat mai sus).

Semnătura argumentului pentru tipurile.MethodType este (funcție, instanță, clasă) :

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

și utilizarea:

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

Metoda doi: legarea lexicală

Mai întâi, vom crea o funcție de înfășurare care leagă metoda la instanță:

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

utilizare:

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

Metoda trei: functools.partial

O funcție parțială aplică primul argument (e) unei funcții (și opțional argumentele cuvintelor cheie) și poate fi apelat mai târziu cu argumentele rămase (și argumentele de cuvinte cheie superioare). Prin urmare:

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

Acest lucru are sens atunci când considerați că metodele legate sunt funcții parțiale ale instanței.

Funcția neviabilă ca atribut obiect - de ce nu funcționează:

Dacă încercăm să adăugăm metoda sample_method în același mod pe care l-am putea adăuga la clasă, ea este nelegată de instanță și nu acceptă sinele implicit ca primul argument.

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

Putem face funcția nelegată să treacă în mod explicit instanța (sau orice, deoarece această metodă nu utilizează de fapt variabila argumentului auto ), dar nu ar fi în concordanță cu semnătura așteptată a altor instanțe (dacă suntem de maimuță-patching acest exemplu):

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

Concluzie

Acum știți mai multe moduri în care puteți face acest lucru, dar cu toată seriozitatea - nu faceți asta.

0
adăugat
Comentariul meu sa bazat pe această referință: python-reference.readthedocs. io / ro / latest / docs / dunderdsc / & hellip; Ceea ce văd acum din documentele oficiale, este opțional: docs.python.org/3/howto/descriptor.html#descriptor-protocol
adăugat autor Aidas Bendoraitis
Metoda __ get __ are de asemenea nevoie de clasă ca următorul parametru: sample_method .__ get __ (foo, Foo) .
adăugat autor Aidas Bendoraitis
@AidasBendoraitis Nu aș spune că "are nevoie" de ea, este un parametru opțional furnizat atunci când se aplică protocolul descriptor - dar funcțiile python nu utilizează argumentul:
adăugat autor Aaron Hall
@Atold Am extins motivele pentru a evita acest lucru în introducere.
adăugat autor Aaron Hall
Disclaimerul este ceea ce mă întrebam. Definițiile de metode sunt pur și simplu funcții imbricate în cadrul definiției clasei.
adăugat autor Atcold

Module new is deprecated since python 2.6 and removed in 3.0, use types

see http://docs.python.org/library/new.html

În exemplul de mai jos am eliminat în mod deliberat valoarea returnată din funcția patch_me () . Cred că dăruirea valorii returnate poate face ca cineva să creadă că patch-ul returnează un obiect nou, ceea ce nu este adevărat - modifică intrarea. Probabil acest lucru poate facilita o utilizare mai disciplinată a monkeypatching-ului.

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 
0
adăugat

Există cel puțin două moduri de a atașa o metodă la o instanță fără types.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
<__main__.A instance at 0x973ec6c>>
>>> 
>>> def foo(firstargument):
...  print 'im foo, invoked with: ', firstargument

>>> foo

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
<__main__.A instance at 0x973ec6c>>

2:

>>> instancemethod = type(A.m)
>>> instancemethod

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

Useful links:
Data model - invoking descriptors
Descriptor HowTo Guide - invoking descriptors

0
adăugat

Deoarece această întrebare a fost solicitată pentru versiuni non-Python, iată JavaScript:

a.methodname = function () { console.log("Yay, a new method!") }
0
adăugat

Cred că răspunsurile de mai sus au ratat punctul cheie.

Să avem o clasă cu o metodă:

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

Acum, să ne jucăm cu ipython:

In [2]: A.m
Out[2]: 

Ok, astfel m () devine cumva o metodă nelegată de A . Dar este chiar așa?

In [5]: A.__dict__['m']
Out[5]: 

Se pare că m () este doar o funcție, referință la care se adaugă un dicționar de clasă A - nu există magie. Atunci de ce A.m ne oferă o metodă nelegată? Acest lucru se datorează faptului că punctul nu este tradus la o căutare simplă a dicționarului. Este de facto o chemare a clasei A .__ __.__ 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
 - m
 - m

Acum, nu sunt sigur că din capul capului meu de ce ultima linie este tipărită de două ori, dar totuși este clar ce se întâmplă acolo.

Acum, ceea ce face implicit __getattribute__ este că verifică dacă atributul este așa-numitul descriptor sau nu, adică dacă implementează o metodă specială __get__. Dacă implementează acea metodă, atunci ceea ce este returnat este rezultatul chemării metodei __get__. Revenind la prima versiune a clasei noastre A , aceasta este ceea ce avem:

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

Și deoarece funcțiile Python implementează protocolul descriptor, dacă sunt chemați în numele unui obiect, se leagă de obiectul respectiv prin metoda lor __get__.

Ok, deci cum să adăugați o metodă unui obiect existent? Presupunând că nu vă deranjează clasa de patch-uri, este la fel de simplă:

B.m = m

Apoi, B.m "devine" o metodă nelegată, datorită magiei descriptorilor.

Și dacă doriți să adăugați o metodă doar unui singur obiect, atunci trebuie să emulați mașina cu ajutorul tipurilor. Metoda Tip:

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

Apropo:

In [2]: A.m
Out[2]: 

In [59]: type(A.m)
Out[59]: 

In [60]: type(b.m)
Out[60]: 

In [61]: types.MethodType
Out[61]: 
0
adăugat

Această întrebare a fost deschisă cu ani în urmă, dar hei, există o modalitate ușoară de a simula legarea unei funcții într-o instanță de clasă folosind decoratori:

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 ()

There, when you pass the function and the instance to the binder decorator, it will create a new function, with the same code object as the first one. Then, the given instance of the class is stored in an attribute of the newly created function. The decorator return a (third) function calling automatically the copied function, giving the instance as the first parameter.

In conclusion you get a function simulating it's binding to the class instance. Letting the original function unchanged.

0
adăugat

Consolidarea răspunsurilor lui Jason Pratt și a comunității wiki, cu privire la rezultatele diferitelor metode de legare:

Notați mai ales cum adăugați funcția de legare ca metodă de clasă funcționează , dar domeniul de referință este incorect.

#!/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__ <__main__.C instance at 0x000000000230FD88>>
# addmethod <__main__.C instance at 0x000000000230FD88>>
# f0 <__main__.C instance at 0x000000000230FD88>>

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

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

Personal, prefer calea externă a funcției ADDMETHOD, deoarece îmi permite să atribuie dinamic noi nume de metode în cadrul unui iterator.

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__ <__main__.C instance at 0x0000000002303508>>
# addmethod <__main__.C instance at 0x0000000002303508>>
# f0 <__main__.C instance at 0x0000000002303508>>
# f1 <__main__.C instance at 0x0000000002303508>>
# f2 <__main__.C instance at 0x0000000002303508>>
# f3 <__main__.C instance at 0x0000000002303508>>
# f4 <__main__.C instance at 0x0000000002303508>>
0
adăugat
addmethod rescris în următorul mod def addmethod (auto, metoda, nume): self .__ dict __ [name] = types.MethodType (method, self)
adăugat autor Antony Hatchkins

În patch-ul maimuțelor Python funcționează în general prin suprascrierea unei clase sau a unei funcții de semnătură cu propria dvs. Mai jos este un exemplu din Zope Wiki :

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

Acest cod va suprascrie / crea o metodă numită vorbi în clasă. În recenta postare pe patching de maimuță de Jeff Atwood . El arată un exemplu în C # 3.0, care este limba curentă pe care o folosesc pentru muncă.

0
adăugat
Dar ea influențează toate instanțele clasei, nu doar una.
adăugat autor glglgl

În Python, există o diferență între funcții și metode legate.

>>> def foo():
...     print "foo"
...
>>> class A:
...     def bar( self ):
...         print "bar"
...
>>> a = A()
>>> foo

>>> a.bar
<__main__.A instance at 0x00A9BC88>>
>>>

Metodele legate au fost "legate" (cât de descriptive) la o instanță, iar acea instanță va fi trecută ca primul argument ori de câte ori este apelată metoda.

Callabilele care sunt atribute ale unei clase (spre deosebire de o instanță) sunt încă nelegate, deși astfel puteți modifica definiția clasei ori de câte ori doriți:

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

Formatele definite anterior sunt actualizate, de asemenea (atâta timp cât ele nu au înlocuit ele însele atributul):

>>> a.fooFighters()
fooFighters

Problema apare atunci când doriți să atașați o metodă la o singură instanță:

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

Funcția nu este legată automat atunci când este atașată direct la o instanță:

>>> a.barFighters

Pentru a le lega, putem folosi funcția MethodType în modulul types :

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

De data aceasta, alte exemple ale clasei nu au fost afectate:

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

Mai multe informații pot fi găsite prin citirea descriptorilor și metaclas programare .

0
adăugat
Sunt metode legate în Python similare cu metodele de extensii din C #?
adăugat autor Andy
@EndermanAPM: Mai multe: este mai probabil să continuați să lucrați exact la fel ca ceea ce face accesarea atributului pe o instanță. Va funcționa pentru classmethod și staticmethod și pentru alți descriptori. Se evită aglomerația spațiului de nume cu încă un alt import.
adăugat autor Martijn Pieters
Codul complet pentru abordarea descriptorului sugerat este a.barFighters = barFighters .__ get __ (a)
adăugat autor eqzx
@MartijnPietează orice avantaje de folosire a protocolului descriptor vs crearea unui MethodType în afară de faptul că este puțin mai ușor de citit.
adăugat autor EndermanAPM

Ceea ce a postat Jason Pratt este corect.

>>> class Test(object):
...   def a(self):
...     pass
... 
>>> def b(self):
...   pass
... 
>>> Test.b = b
>>> type(b)

>>> type(Test.a)

>>> type(Test.b)

După cum puteți vedea, Python nu consideră b () altfel decât a (). În Python toate metodele sunt doar variabile care se întâmplă să fie funcții.

0
adăugat
Pachetați codul Test , nu o instanță a acestuia.
adăugat autor Ethan Furman

Trebuie să vă uitați într-adevăr la fructe interzise , este o bibliotecă python care oferă suport pentru maimuță patching ORICE clasă python, chiar si siruri de caractere.

0
adăugat
În general, link-urile către un instrument sau bibliotecă ar trebui să fie însoțite de note de utilizare sau de un exemplu de cod sau, dacă este posibil, ambele. Cu toate acestea, aceasta îndeplinește cel puțin standardul minim în postul conectat, prin includerea unei explicații specifice a modului în care resursa asociată este aplicabilă problemei.
adăugat autor Nathan Tuggy

Dacă poate fi de ajutor, am lansat recent o bibliotecă Python numită Gorilla pentru a face procesul de împachetare a maimuțelor mai convenabil.

Folosind o funcție needle () pentru a patch-uri un modul numit guineapig merge după cum urmează:

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

Dar, de asemenea, are grijă de cazuri de utilizare mai interesante, așa cum se arată în Întrebări frecvente din documentație .

Codul este disponibil pe GitHub .

0
adăugat

Puteți folosi lambda pentru a lega o metodă într-o instanță:

def run(self):
    print self._instanceString

class A(object):
    def __init__(self):
        self._instanceString = "Acesta este șirul de instanțe"

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

Acesta este șirul de instanțe

Procesul a terminat cu codul de iesire 0

0
adăugat

Acesta este de fapt un addon la răspunsul "Jason Pratt"

Deși răspunsul Jason funcționează, funcționează numai dacă doriți să adăugați o funcție unei clase. Nu a funcționat pentru mine când am încercat să reîncarcă o metodă deja existentă din fișierul cu codul sursă .py.

Mi-a trebuit mult timp să găsesc o soluție, dar trucul pare simplu ... 1.importați codul din fișierul cu cod sursă 2.nd forța o reîncărcare 3.rd utilizează types.FunctionType (...) pentru a converti metoda importată și legată la o funcție puteți transmite și variabilele globale actuale, deoarece metoda reîncărcată ar fi într-un spațiu de nume diferit 4. acum puteți continua așa cum a sugerat "Jason Pratt"   utilizând tipurile.MethodType (...)

Exemplu:

# 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
0
adăugat

Mi se pare ciudat că nimeni nu a menționat că toate metodele enumerate mai sus creează o referință de ciclu între metoda adăugată și instanță, determinând obiectul să fie persistent până la colectarea gunoiului. A existat un truc vechi care adaugă un descriptor prin extinderea clasei obiectului:

def addmethod(obj, name, func):
    klass = obj.__class__
    subclass = type(klass.__name__, (klass,), {})
    setattr(subclass, name, func)
    obj.__class__ = subclass
0
adăugat
from types import MethodType

def method(self):
   print 'hi!'


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

Cu aceasta puteți utiliza indicatorul auto

0
adăugat