Dodawanie metodę do istniejącej instancji obiektu

głosy
488

Czytałem, że jest możliwe, aby dodać metodę do istniejącego obiektu (czyli nie w definicji klasy) w Pythonie.

Rozumiem, że nie zawsze jest dobre, aby to zrobić. Ale jak można to zrobić?

Utwórz 04/08/2008 o 03:17
źródło użytkownik
W innych językach...                            


18 odpowiedzi

głosy
736

W Pythonie istnieje różnica między funkcjami i metod związanych.

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

Związane metody zostały „związany” (jak opisowe) do instancji i że instancja zostanie przekazana jako pierwszy argument, gdy wywoływana jest metoda.

Callables które są atrybuty klasy (w przeciwieństwie do instancji) są nadal niezwiązany, choć, więc można zmodyfikować definicję klasy, kiedy tylko chcesz:

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

Wcześniej zdefiniowane przypadki są aktualizowane w miarę dobrze (o ile nie zostały one zastąpione atrybutem siebie):

>>> a.fooFighters()
fooFighters

Problem pojawia się, gdy chcesz dołączyć metodę pojedynczej instancji:

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

Funkcja ta nie jest automatycznie, gdy jest ona związana bezpośrednio przyłączone do instancji:

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

Związać go, możemy użyć funkcji MethodType w module typy :

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

Tym razem inne instancje klasy nie zostały naruszone:

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

Więcej informacji można znaleźć czytając o deskryptorów i metaklasa programowania .

Odpowiedział 06/08/2008 o 01:33
źródło użytkownik

głosy
80

Moduł nowy jest przestarzała od Pythona 2.6 i 3.0, usunięte w użytku rodzajów

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

W poniższym przykładzie ja celowo usunięte wartość zwracana z patch_me()funkcji. Myślę, że podawanie wartości zwracanej mogą wierzyć, że łata zwraca nowy obiekt, który nie jest prawdą - to modyfikuje jedną przychodzące. Prawdopodobnie może to ułatwić bardziej zdyscyplinowane stosowanie monkeypatching.

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'>
Odpowiedział 06/06/2009 o 06:31
źródło użytkownik

głosy
47

Dodawanie metodę do istniejącej instancji obiektu

Czytałem, że jest możliwe, aby dodać metodę do istniejącego obiektu (na przykład nie w definicji klasy) w Pythonie.

Rozumiem, że nie zawsze jest to dobra decyzja, aby to zrobić. Ale, jak można to zrobić?

Tak, to jest możliwe - ale nie jest zalecany

Nie polecam tego produktu. To jest zły pomysł. Nie rób tego.

Oto kilka powodów:

  • Musisz dodać obiekt związany do każdej instancji to robisz. Jeśli zrobisz to dużo, prawdopodobnie będziesz tracić pamięć. Związane metody są zwykle tworzone tylko przez krótki czas ich rozmowy, a oni wtedy, gdy przestanie istnieć automatycznie zbierane śmieci. Jeśli to zrobić ręcznie, będziesz mieć nazwę wiązania przedstawieniu metodę związaną - co zapobiegnie ich zbieranie śmieci zużycia.
  • Przykłady obiektów danego typu mają zwykle stosowanych metod do wszystkich obiektów tego typu. Jeśli dodać metod gdzie indziej, niektóre przypadki będą miały te metody, a inni nie. Programiści nie będą oczekiwać tego, a istnieje ryzyko naruszania zasady najmniejszego zaskoczenia .
  • Ponieważ istnieją inne naprawdę dobre powody, aby tego nie zrobisz, dodatkowo dać sobie złą reputację, jeśli to zrobić.

Tak więc uważam, że nie to zrobić, chyba że masz naprawdę dobry powód. Jest to znacznie lepiej ustalić odpowiednią metodę w definicji klasy lub mniej korzystnie małpy plastra klasa bezpośrednio, na przykład:

Foo.sample_method = sample_method

Ponieważ jest to pouczające, jednak mam zamiar pokazać wam kilka sposobów robienia tego.

Jak można to zrobić

Oto niektóre kodu konfiguracji. Musimy definicji klasy. To może być importowane, ale to naprawdę nie ma znaczenia.

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

Tworzenie instancji:

foo = Foo()

Utworzyć metodę dodawania do niego:

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

Metoda zero (0) - użyj metody deskryptora, __get__

Przerywane wyszukiwań w funkcji wywołać __get__sposób funkcji o przykład wiązania obiektu sposobu, a tym samym tworzenie się „metodę ograniczenia”.

foo.sample_method = sample_method.__get__(foo)

i teraz:

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

Sposób pierwszy - types.MethodType

Po pierwsze, typy importu, z którego będziemy się konstruktora metoda:

import types

Teraz dodamy metodę instancji. Aby to zrobić, potrzebujemy konstruktora MethodType z typesmodułu (który sprowadziliśmy powyżej).

Podpis argument za types.MethodType jest (function, instance, class):

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

i użytkowanie:

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

Sposób drugi: leksykalny wiązania

Po pierwsze, możemy utworzyć funkcję otoki, który wiąże metodę instancji:

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

stosowanie:

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

Sposób trzeci: functools.partial

Częściowa funkcja dotyczy pierwszy argument (y) do funkcji (i argumentów ewentualnie kluczowych), a później może zostać wywołany z pozostałych argumentów (i nadrzędne argumentów kluczowych). A zatem:

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

Ma to sens, jeśli wziąć pod uwagę, że metody bound są częściowymi funkcje instancji.

Bez ograniczeń funkcja jako atrybut obiektu - dlaczego to nie działa:

Jeśli staramy się dodać sample_method w taki sam sposób, jak możemy go dodać do klasy, jest niezwiązany z instancji, a nie podejmują niejawnego self jako pierwszy 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)

Możemy wykonać pracę niezwiązaną funkcji jawnie przekazując instancję (lub czegokolwiek, ponieważ ta metoda nie faktycznie używać selfzmiennej argument), ale to nie byłoby zgodne z przewidywanym podpisaniem innych przypadkach (jeśli jesteśmy małpa-łatanie Ten przykład):

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

Wniosek

Teraz wiesz kilka sposobów, dzięki którym mógłby to zrobić, ale z całą powagą - nie rób tego.

Odpowiedział 21/01/2015 o 05:31
źródło użytkownik

głosy
30

Myślę, że powyższe odpowiedzi brakowało kluczowy punkt.

Rzućmy klasę z metodą:

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

A teraz grać z nim w ipython:

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

Ok, m () w jakiś sposób staje się niezwiązany Sposób . Ale czy to naprawdę tak?

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

Okazuje się, że m () jest tylko funkcja, odniesienie do którego dodaje się do A słowniku klasy - nie ma magii. Więc dlaczego Am daje nam sposób niezwiązany? To dlatego, że kropki nie są tłumaczone na prostym słowniku odnośnika. Jest to de facto wezwanie A .__ class __.__ 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

Teraz nie jestem pewien z góry głowę, dlaczego ostatnia linia jest drukowana dwa razy, ale mimo to jest jasne, co się tam dzieje.

Teraz, co domyślny __getattribute__ robi jest to, że sprawdza, czy atrybut jest tzw deskryptor , czy nie, to znaczy jeżeli realizuje specjalną metodę __get__. Jeżeli realizuje tę metodę, to co jest zwracany jest wynik wywołania tej metody __get__. Wracając do pierwszej wersji naszej A klasy, to co mamy:

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

A ponieważ funkcje Python deskryptora wdrożenia protokołu, jeżeli są one nazywane w imieniu obiektu, wiążą się do tego obiektu w ich sposobie __get__.

Ok, tak jak dodać metodę do istniejącego obiektu? Zakładając, że nie przeszkadza łatanie klasę, jest to tak proste, jak:

B.m = m

Następnie Bm „staje się” metoda niezwiązany, dzięki magii deskryptora.

A jeśli chcesz dodać metodę tylko do pojedynczego obiektu, a następnie trzeba naśladować maszyny samodzielnie, za pomocą types.MethodType:

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

Tak poza tym:

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'>
Odpowiedział 22/01/2012 o 15:20
źródło użytkownik

głosy
16

W Pythonie małpa łatanie działa zazwyczaj poprzez nadpisanie klasy lub funkcji podpisu własną rękę. Poniżej znajduje się przykład z Zope Wiki :

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

Że kod będzie zastępowanie / utworzyć metodę zwaną mówić o klasie. W Jeff Atwood w ostatnim poście na małpy łatania . On pokazuje przykład w C # 3.0, który jest obecny język używam do pracy.

Odpowiedział 04/08/2008 o 03:31
źródło użytkownik

głosy
9

Istnieją co najmniej dwa sposoby dołączyć metodę instancji bez 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
<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>>

Przydatne linki:
Model danych - wywołanie deskryptory
deskryptorów HowTo Przewodnik - wywołanie deskryptory

Odpowiedział 26/04/2013 o 16:47
źródło użytkownik

głosy
7

Można użyć lambda powiązać metodę instancji:

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

To jest przykład ciąg

Proces zakończony z kodem wyjściowym 0

Odpowiedział 21/07/2014 o 13:55
źródło użytkownik

głosy
6

Od tego pytanie zadane w wersji non-python, oto JavaScript:

a.methodname = function () { console.log("Yay, a new method!") }
Odpowiedział 09/03/2012 o 16:07
źródło użytkownik

głosy
6

Co szukasz to setattrwierzę. Użyj tego, aby ustawić atrybut na obiekcie.

>>> 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>
Odpowiedział 07/08/2008 o 12:30
źródło użytkownik

głosy
5

To jest rzeczywiście dodatek do odpowiedzi z „Jason Pratt”

Chociaż Jasons odpowiedzieć działa, to działa tylko wtedy, gdy chce się dodać funkcję do klasy. To nie dla mnie, kiedy próbował przeładować już istniejące metody z pliku kodu źródłowego .py.

Zajęło mi wieki, aby znaleźć sposób obejścia problemu, ale trick wydaje się prosta ... 1.st importować kod z pliku kodu źródłowego 2.nd wymusić types.FunctionType użycia przeładowania 3.rd (...) do konwersji importowane i związany metoda do funkcji można również przekazać na obecnych zmiennych globalnych, ponieważ przeładowane metoda byłaby w innej przestrzeni nazw 4.th teraz można kontynuować jak sugeruje „Jason Pratt” używając types.MethodType (... )

Przykład:

# 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
Odpowiedział 18/08/2015 o 15:32
źródło użytkownik

głosy
5

Wy naprawdę powinny wyglądać w zakazanego owocu , to biblioteka Pythona, który zapewnia wsparcie dla małpy łatanie Każda klasa Pythona, nawet sznurki.

Odpowiedział 25/08/2013 o 22:56
źródło użytkownik

głosy
5

Konsolidacja Jason Pratt i wiki społeczność odpowiedzi, z okiem na wyniki różnych sposobów wiązania:

Szczególnie zwrócić uwagę w jaki sposób dodanie funkcji wiążącej jako metoda klasy działa , ale zakres przedstawieniu jest nieprawidłowy.

#!/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>>

Osobiście wolę zewnętrzną trasą funkcja ADDMETHOD, gdyż pozwala mi dynamicznie przydzielać nowe nazwy metody w iteratora również.

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>>
Odpowiedział 28/01/2012 o 01:12
źródło użytkownik

głosy
4

Co Jason Pratt pisał jest poprawna.

>>> 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'>

Jak widać, Python nie uważa b () inaczej niż (). W Pythonie wszystkie metody są tak zmienne, że stało się funkcje.

Odpowiedział 22/08/2008 o 15:40
źródło użytkownik

głosy
3

Jeśli może być żadnej pomocy, niedawno zwolniony biblioteki Pythona o nazwie Gorilla aby proces małpy łatanie wygodniejsze.

Korzystanie z funkcji needle()załatać moduł nazwany guineapigjest następujący:

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

Ale również dba o ciekawszych przypadków użycia, jak pokazano w FAQ z dokumentacją .

Kod jest dostępny na GitHub .

Odpowiedział 15/07/2014 o 03:12
źródło użytkownik

głosy
2

Znaleźć dziwne, że nikt nie zauważyć, że wszystkie powyżej wymienione sposoby tworzy odniesienie cyklu między dodanym sposobu i przykład, przedmiot może być trwałe do zbierania śmieci. Nie był stary trik dodając deskryptor rozszerzając klasę obiektu:

def addmethod(obj, name, func):
    klass = obj.__class__
    subclass = type(klass.__name__, (klass,), {})
    setattr(subclass, name, func)
    obj.__class__ = subclass
Odpowiedział 30/04/2017 o 04:57
źródło użytkownik

głosy
2

Ta kwestia została otwarta rok temu, ale hej, jest tam łatwy sposób symulować wiązanie funkcję do instancji klasy używając dekoratorów:

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

Tam, kiedy przechodzą funkcję i wystąpienie do dekoratora spoiwa, stworzy nową funkcję, z tego samego przedmiotu kod jako pierwszy. Następnie dana instancja klasy jest przechowywana w atrybucie funkcji nowo utworzone. Dekorator zwrócić (trzeciego) funkcję automatycznego wywoływania funkcji skopiowany, dając instancję jako pierwszy parametr.

Podsumowując można uzyskać funkcję symulacji to wiązanie do instancji klasy. Pozwalając pierwotna funkcja zmian.

Odpowiedział 21/12/2015 o 21:39
źródło użytkownik

głosy
1
from types import MethodType

def method(self):
   print 'hi!'


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

Z tym, można użyć wskaźnika samodzielne

Odpowiedział 27/07/2017 o 04:21
źródło użytkownik

głosy
-8

Nie wiem składni Pythona, ale wiem Ruby może to zrobić, i to dość trywialne. Powiedzmy, że chcesz dodać metodę Array że drukuje długość na standardowe wyjście:

class Array
  def print_length
    puts length
  end
end

Jeśli nie chcesz modyfikować całą klasę, można po prostu dodać metodę do jednej instancji tablicy, a nie inne tablice będą miały metody:

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

Wystarczy mieć świadomość zagadnień związanych z wykorzystaniem tej funkcji. Jeff Atwood faktycznie napisał o nim nie tak dawno temu.

Odpowiedział 04/08/2008 o 03:36
źródło użytkownik

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more