Додавання методу до існуючого об'єкта


642

Я читав, що в Python можна додати метод до вже існуючого об'єкта (тобто не у визначенні класу).

Я розумію, що це не завжди добре робити. Але як це можна зробити?

Відповіді:


921

У Python існує різниця між функціями та прив’язаними методами.

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

Методи зв’язку були "прив'язані" (як описово) до екземпляра, і цей екземпляр буде переданий як перший аргумент щоразу, коли метод викликається.

Дзвінки, що є атрибутами класу (на відміну від екземпляра), все ще є незв'язаними, тому ви можете змінювати визначення класу коли завгодно:

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

Попередньо визначені екземпляри також оновлюються (до тих пір, поки вони самі не змінили атрибут):

>>> a.fooFighters()
fooFighters

Проблема виникає, коли ви хочете приєднати метод до одного примірника:

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

Функція не пов'язана автоматично, якщо вона приєднана безпосередньо до екземпляра:

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

Щоб прив'язати його, ми можемо використовувати функцію MethodType в модулі типів :

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

Цього разу інші екземпляри класу не вплинули:

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

Більше інформації можна отримати, прочитавши про дескриптори та програмування метакласу .


65
Замість того, щоб створювати вручну MethodType, виклик протоколу дескриптора вручну, і функція виробляє ваш екземпляр: barFighters.__get__(a)виробляє прив'язаний метод для barFightersприв'язки до a.
Martijn Pieters

2
@MartijnPieters будь-які переваги використання descriptor protocolvs, створюючи MethodTypeосторонь, можливо, бути трохи читабельнішим.
EndermanAPM

17
@EndermanAPM: Кілька: більше шансів продовжувати працювати точно так само, як це робить доступ до атрибута в екземплярі. Він буде працювати classmethodі staticmethodта інші дескриптори теж. Це дозволяє уникнути захаращення простору імен ще одним імпортом.
Martijn Pieters

34
Повний код запропонованого дескрипторного підходуa.barFighters = barFighters.__get__(a)
eqzx

98

Модуль new застарілий з python 2.6 та видалений у 3.0, типів використання

див. http://docs.python.org/library/new.html

У наведеному нижче прикладі я навмисно видалив зворотне значення з patch_me()функції. Я думаю, що надання повернення значення може змусити повірити, що патч повертає новий об'єкт, що не відповідає дійсності - це змінює вхідний. Ймовірно, це може сприяти більш дисциплінованому використанню маніпулювання.

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

1
Як би це діяло, якщо доданий метод потребує посилання на себе? Моя перша спроба призводить до синтаксичної помилки, але додавання self у визначенні методу, здається, не працює. типи імпорту класу A (об'єкт): # але, здається, працює для старих об'єктів стилю також ax = 'ax' pass def patch_me (target): метод def (target, x): print (self.ax) print ("x =" , x) print ("викликається з", target) target.method = types.MethodType (метод, ціль) #add більше, якщо потрібно a = A () print (a.ax)
WesR

85

Передмова - примітка про сумісність: інші відповіді можуть працювати лише в Python 2 - ця відповідь повинна відмінно працювати в Python 2 та 3. Якщо писати лише Python 3, ви можете явно не залишитися у спадок object, але в іншому випадку код повинен залишатися тим самим .

Додавання методу до існуючого об'єкта

Я читав, що в Python можна додати метод до вже існуючого об'єкта (наприклад, не у визначенні класу).

Я розумію, що це не завжди добре рішення. Але, як це можна зробити?

Так, можливо - Але не рекомендується

Я не рекомендую цього. Це погана ідея. Не робіть цього.

Ось кілька причин:

  • Ви додасте зв'язаний об'єкт до кожного екземпляра, для якого це робите. Якщо ви цим займаєтеся багато, ви, ймовірно, витратите багато пам’яті. Сполучені методи, як правило, створюються лише на короткий час їх дзвінка, і вони припиняють своє існування, коли автоматично збирається сміття. Якщо це зробити вручну, ви будете мати прив'язку до імені, що посилається на зв'язаний метод - це запобіжить його збору сміття під час використання.
  • Екземпляри об'єктів даного типу зазвичай мають свої методи для всіх об'єктів цього типу. Якщо ви додасте методи в іншому місці, в деяких екземплярах ці методи знайдуться, а в інших - не. Програмісти цього не очікують, і ви ризикуєте порушити правило про найменший сюрприз .
  • Оскільки є й інші справді вагомі причини цього не робити, ви додатково надасте собі погану репутацію, якщо це зробите.

Таким чином, я пропоную вам цього не робити, якщо у вас є справді вагомі причини. Набагато краще визначити правильний метод у визначенні класу або менш бажано, щоб мавпа-патч класу безпосередньо, як це:

Foo.sample_method = sample_method

Однак, оскільки це повчально, я збираюся показати вам деякі способи цього.

Як це можна зробити

Ось якийсь код налаштування. Нам потрібно визначення класу. Її можна імпортувати, але це насправді не має значення.

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

Створіть примірник:

foo = Foo()

Створіть метод для додавання до нього:

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

Метод nught (0) - використовувати метод дескриптора, __get__

Точкові пошуки функцій викликають __get__метод функції з екземпляром, прив'язуючи об'єкт до методу і таким чином створюючи "прив'язаний метод".

foo.sample_method = sample_method.__get__(foo)

і зараз:

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

Перший метод - типи

По-перше, типи імпорту, з яких ми отримаємо конструктор методу:

import types

Тепер ми додаємо метод до екземпляра. Для цього нам потрібен конструктор MethodType від typesмодуля (який ми імпортували вище).

Підпис аргументу для типів.MethodType (function, instance, class):

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

та використання:

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

Спосіб другий: лексичне зв’язування

Спочатку ми створюємо функцію обгортки, яка прив'язує метод до примірника:

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

використання:

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

Спосіб третій: functools.partial

Часткова функція застосовує перший аргумент (и) до функції (і необов'язково аргументи ключових слів), а згодом може бути викликана за допомогою решти аргументів (і переосмислених аргументів ключових слів). Таким чином:

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

Це має сенс, якщо врахувати, що зв'язані методи - це часткові функції екземпляра.

Функція відключення як атрибут об'єкта - чому це не працює:

Якщо ми спробуємо додати sample_method таким же чином, як і ми можемо додати його до класу, він не пов'язаний з екземпляром, і не приймає неявну самості як перший аргумент.

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

Ми можемо змусити функцію незв'язаного працювати, явно передаючи екземпляр (або що завгодно, оскільки цей метод насправді не використовує selfзмінну аргументу), але це не буде відповідати очікуваному підпису інших екземплярів (якщо ми будемо виправляти мавпи цей примірник):

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

Висновок

Тепер ви знаєте кілька способів, як ви могли це зробити, але з усією серйозністю - не робіть цього.


1
Відмова від відповідальності є те , що мені було цікаво , о. Визначення методів - це просто функції, вкладені в визначення класу.
Atcold

1
@Atcold Я розширив причини, щоб уникнути цього у вступі.
Аарон Холл

__get__Метод також необхідний клас в якості наступного параметра: sample_method.__get__(foo, Foo).
Айдас Бендораїт

2
@AidasBendoraitis Я б не сказав, що це "потребує", це необов'язковий параметр, який надається при застосуванні протоколу дескриптора - але функції python не використовують аргумент: github.com/python/cpython/blob/master/Objects/funcobject .c # L581
Aaron Hall

Мій коментар ґрунтувався на цій посиланні: python-reference.readthedocs.io/en/latest/docs/dunderdsc/… Що я бачу з офіційних документів, це необов'язково: docs.python.org/3/howto/descriptor.html# дескриптор-протокол
Aidas Bendoraitis

35

Я думаю, що наведені відповіді пропустили ключовий момент.

Давайте мати клас із методом:

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

Тепер давайте пограємо з ним в ipython:

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

Отже, м () який - то чином стає непов'язаним методом А . Але це насправді так?

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

Виявляється, m () - це лише функція, посилання на яку додається до словника класу A - ніякої магії немає. Тоді чому Ам дає нам незв'язаний метод? Це тому, що крапка не перекладається на простий пошук словника. Це фактично виклик класу 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
<class '__main__.A'> - m
<class '__main__.A'> - m

Тепер я не впевнений, що в голові, чому останній рядок надруковано двічі, але все одно зрозуміло, що там відбувається.

Тепер, що __getattribute__ робить за замовчуванням, це те, що він перевіряє, чи атрибут є так званим дескриптором чи ні, тобто, якщо він реалізує спеціальний метод __get__. Якщо він реалізує цей метод, то те, що повертається, є результатом виклику цього методу __get__. Повертаючись до першої версії нашого класу A , це те, що ми маємо:

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

А оскільки функції Python реалізують протокол дескриптора, якщо вони викликаються від імені об'єкта, вони прив'язують себе до цього об'єкта у своєму методі __get__.

Гаразд, так як додати метод до існуючого об'єкта? Якщо припустити, що ви не проти класу виправлення, це так просто, як:

B.m = m

Тоді Bm "стає" незв'язаним методом, завдяки магії дескриптора.

І якщо ви хочете додати метод лише до одного об’єкта, вам доведеться самостійно емулювати техніку, використовуючи type.MethodType:

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

Між іншим:

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

19

У Python мавпа виправлення, як правило, працює, замінивши підпис класу або функцій власноруч. Нижче наведено приклад із Zope Wiki :

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

Цей код замінить / створить метод, який називається говорить на уроці. У недавньому дописі Джеффа Етвуда про виправлення мавп . Він показує приклад на C # 3.0, який є поточною мовою, яку я використовую для роботи.


6
Але це впливає на всі екземпляри класу, не лише одну.
glglgl

14

Ви можете використовувати lambda для прив'язки методу до примірника:

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

Вихід:

This is instance string

9

Є принаймні два способи приєднання методу до екземпляра без 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>>

Корисні посилання:
Модель даних - виклик дескрипторів
Дескриптор HowTo Guide - виклик дескрипторів


7

Те, що ви шукаєте, setattrя вірю. Використовуйте це, щоб встановити атрибут об’єкта.

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

8
Це виправлення класу A, а не екземпляр a.
Етан Фурман

5
Чи є причина використовувати setattr(A,'printme',printme)замість просто A.printme = printme?
Тобіас Кіенцлер

1
Це має сенс, якщо під час виконання конструювати назву методу.
rr-

6

Оскільки це запитання задано для не-Python версій, ось JavaScript:

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

5

Консолідація відповідей Джейсона Пратта та вікі спільноти з поглядом на результати різних методів зв'язування:

Особливо зверніть увагу , як додавання функції прив'язки в якості методу класу робіт , але посилання сфери невірна.

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

Особисто я віддаю перевагу зовнішньому маршруту функції ADDMETHOD, оскільки він дозволяє мені динамічно призначати нові імена методів і в ітераторі.

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

addmethodпереписана таким чином def addmethod(self, method, name): self.__dict__[name] = types.MethodType( method, self )вирішує проблему
Ентоні Хеткінс

5

Це насправді доповнення до відповіді "Джейсон Пратт"

Хоча відповідь Ясона працює, вона працює лише в тому випадку, якщо хочеться додати функцію до класу. Мені це не вийшло, коли я спробував перезавантажити вже існуючий метод із файлу вихідного коду .py.

Мені знадобилося віки, щоб знайти вирішення, але хитрість здається простою ... 1. імпортувати код з файлу вихідного коду 2. і змусити перезавантажити 3.rd use types.FunctionType (...) для перетворення імпортований і прив'язаний метод до функції, ви також можете передавати поточні глобальні змінні, оскільки перезавантажений метод знаходився б в іншому просторі імен 4. тепер ви можете продовжувати так, як запропонував "Джейсон Пратт", використовуючи types.MethodType (... )

Приклад:

# 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

3

Якщо це може допомогти, я нещодавно випустив бібліотеку Python під назвою Gorilla, щоб зробити процес виправлення мавп більш зручним.

Використання функції needle()для виправлення модуля з назвою guineapigйде наступним чином:

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

Але він також бере участь у більш цікавих випадках використання, як показано у FAQ із документації .

Код доступний на GitHub .


3

Це питання було відкрито років тому, але ей, існує простий спосіб імітувати прив'язку функції до екземпляра класу за допомогою декораторів:

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

Там, коли ви передасте функцію та екземпляр декоратору сполучень, вона створить нову функцію з тим самим об'єктом коду, що і перша. Потім даний екземпляр класу зберігається в атрибуті новоствореної функції. Декоратор повертає (третю) функцію, яка автоматично викликає скопійовану функцію, надаючи екземпляр в якості першого параметра.

На закінчення ви отримуєте функцію, що імітує прив'язку до екземпляра класу. Залишаючи вихідну функцію незмінною.


2

Те, що розмістив Джейсон Пратт, є правильним.

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

Як бачите, Python не вважає b () відмінним від (). У Python усі методи - це лише змінні, які бувають функціями.


7
Ви виправляєте клас Test, а не його екземпляр.
Етан Фурман

Ви додаєте метод до класу, а не до об'єкта.
TomSawyer

2

Мені здається дивним, що ніхто не згадував, що всі перераховані вище методи створюють посилання на цикл між доданим методом та екземпляром, викликаючи стійкість об'єкта до збору сміття. Старий фокус додав дескриптор шляхом розширення класу об'єкта:

def addmethod(obj, name, func):
    klass = obj.__class__
    subclass = type(klass.__name__, (klass,), {})
    setattr(subclass, name, func)
    obj.__class__ = subclass

2
from types import MethodType

def method(self):
   print 'hi!'


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

За допомогою цього ви можете використовувати вказівник самоврядування

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.