سؤال

لقد قرأت أنه من الممكن إضافة أسلوب إلى كائن موجود (أي ليست في تعريف الفئة) في بيثون.

أنا أفهم أن أنها ليست دائما جيدة للقيام بذلك.ولكن كيف يمكن أن تفعل هذا ؟

هل كانت مفيدة؟

المحلول

في بيثون ، هناك فرق بين وظائف و لا بد الأساليب.

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

لا بد الأساليب "ملزمة" (كيف وصفي) على سبيل المثال ، تلك الحالة سيتم تمرير أول حجة كلما طريقة يسمى.

Callables التي هي سمات فئة (بدلا سبيل المثال) لا تزال غير منضم ، على الرغم من ذلك يمكنك تعديل تعريف الفئة وقتما تشاء:

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

مزيد من المعلومات يمكن العثور عليها عن طريق القراءة عن الواصفات و metaclass البرمجة.

نصائح أخرى

وحدة جديد هو إهمال منذ بيثون 2.6 و إزالتها في 3.0 استخدام أنواع

انظر http://docs.python.org/library/new.html

في المثال أدناه لقد تعمدت إزالة قيمة الإرجاع من patch_me() وظيفة.أعتقد أن إعطاء قيمة الإرجاع قد تجعل المرء يعتقد أن التصحيح بإرجاع كائن جديد ، وهذا غير صحيح - أنه يعدل واردة واحد.وربما هذا يمكن أن تسهل أكثر انضباطا استخدام 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'>

مقدمة - مذكرة بشأن التوافق:إجابات أخرى قد تعمل فقط في بيثون 2 - هذا الجواب يجب أن تعمل بشكل جيد تماما في بيثون 2 و 3.إذا كانت الكتابة بيثون 3 فقط ، قد تترك صراحة وراثة من object, ولكن على خلاف ذلك يجب أن لا تزال هي نفسها.

مضيفا طريقة كائن موجود سبيل المثال

لقد قرأت أنه من الممكن إضافة أسلوب إلى كائن موجود (على سبيل المثالليس في تعريف الفئة) في بيثون.

وأنا أفهم أنه ليس دائما قرارا جيدا للقيام بذلك. ولكن كيف يمكن أن تفعل هذا ؟

نعم من الممكن ولكن لا ينصح

أنا لا أوصي هذا.هذا هو فكرة سيئة.لا تفعل ذلك.

وهنا زوجين من الأسباب:

  • عليك إضافة لا بد كائن إلى كل حالة كنت تفعل هذا.إذا كنت تفعل هذا كثيرا ، ربما سوف تضيع الكثير من الذاكرة.لا بد الأساليب هي عادة فقط التي تم إنشاؤها خلال مدة قصيرة من دعوتهم ، ثم تزول تلقائيا القمامة التي تم جمعها.إذا كان يمكنك القيام بذلك يدويا, سيكون لديك اسم الملزمة الرجوع ملزمة الطريقة - والتي سوف منع جمع القمامة في الاستخدام.
  • مثيلات الكائن من نوع معين عموما لها طرق على جميع الكائنات من هذا النوع.إذا قمت بإضافة طرق أخرى ، بعض الحالات سيكون لديك تلك الأساليب وغيرها لا.المبرمجين لن نتوقع هذا ، هل خطر انتهاك سيادة الأقل مفاجأة.
  • لأن هناك أسباب وجيهة حقا لا تفعل هذا, سوف بالإضافة إلى ذلك تعطي لنفسك سمعة سيئة إذا كنت تفعل ذلك.

وبالتالي أقترح عليك أن لا تفعل هذا إلا إذا كان لديك سبب وجيه حقا. فمن الأفضل بكثير أن تحديد الأسلوب الصحيح في تعريف الفئة أو أقل ويفضل القرد-تصحيح الدرجة بشكل مباشر, مثل هذا:

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)

طريقة صفر (0) - استخدام واصف الأسلوب ، __get__

المنقطة البحث في وظائف الاتصال __get__ طريقة وظيفة مع المثال ربط كائن إلى الأسلوب وبالتالي خلق "لا بد الأسلوب."

foo.sample_method = sample_method.__get__(foo)

و الآن:

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

طريقة واحدة - أنواع.MethodType

أولا استيراد أنواع من خلالها سوف نحصل على الأسلوب المنشئ:

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.جزئية

وظيفة جزئية ينطبق الوسيطة الأولى(s) إلى وظيفة (اختياريا الكلمة الحجج) ، ويمكن أن يكون مع ما تبقى من الحجج (و تجاوز الكلمة الحجج).وبالتالي:

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

الختام

أنت تعرف الآن عدة طرق يمكن أن هل هذا ولكن بكل جدية - لا تفعل هذا.

أعتقد أن الإجابات أعلاه غاب عن النقطة الرئيسية.

دعونا فئة مع الطريقة:

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

الآن, دعونا لعب مع أنه في ipython:

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

حسنا, لذلك م() بطريقة ما يصبح غير منضم طريقة A.ولكن هل هو حقا مثل ذلك ؟

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

اتضح أن م() هو مجرد وظيفة المرجعية التي تضاف إلى A فئة القاموس - لا يوجد سحر.ثم لماذا A. m يعطينا غير منضم الأسلوب ؟ لأن النقطة هي لم تترجم إلى مجرد بحث القاموس.إنه بحكم الواقع مكالمة من أ__الصف__.__getattribute__(أ ، '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__ يفعله هو أن يتحقق إذا كانت السمة هي ما يسمى واصف أو لا ، أيإذا لم تنفذ خاص __على__ طريقة.إذا لم تنفذ هذه الطريقة ، ثم ما عاد هو نتيجة الدعوة التي __على__ طريقة.العودة إلى النسخة الأولى من A فئة, هذا هو ما لدينا:

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

و لأن الثعبان وظائف تنفيذ واصف البروتوكول ، إذا تسمى باسم كائن ، فإنها ربط أنفسهم إلى هذا الكائن في __على__ طريقة.

كيف لإضافة أسلوب كائن موجود?على افتراض انك لا تمانع الترقيع الدرجة, انها بسيطة مثل:

B.m = m

ثم B. m "يصبح" غير منضم الأسلوب ، بفضل واصف السحر.

و إذا كنت ترغب في إضافة وسيلة فقط إلى كائن واحد ، ثم عليك أن تحاكي الآلات نفسك باستخدام أنواع.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'>

في بيثون القرد الترقيع عموما يعمل عن طريق الكتابة فئة أو وظائف التوقيع مع الخاصة بك.وفيما يلي مثال من Zope ويكي:

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

هذا الرمز سيتم الكتابة فوق/إنشاء طريقة تسمى أتكلم على فئة.في جيف أتوود في المشاركة الأخيرة على القرد الترقيع.كان يظهر على سبيل المثال في C# 3.0 الذي هو اللغة الحالية تستخدم في العمل.

هناك اثنين على الأقل من طرق إرفاق طريقة مثيل دون 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 دليل - الاحتجاج واصفات

يمكنك استخدام امدا إلى ربط الأسلوب على سبيل المثال:

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

ما تبحث عنه هو 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>

منذ هذا سؤال غير إصدارات بيثون ، وهنا جافا سكريبت:

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

توحيد جيسون برات والمجتمع ويكي إجابات ، مع نظرة على نتائج أساليب مختلفة من الملزمة:

خاصة ملاحظة كيفية إضافة ملزمة وظيفة من الدرجة طريقة يعمل, لكن الرجوع إلى نطاق غير صحيح.

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

يا رفاق حقا ينبغي أن ننظر الفاكهة المحرمة, إنها مكتبة بيثون التي توفر الدعم القرد الترقيع أي بيثون الدرجة ، حتى السلاسل.

هذا هو في الواقع الملحق إلى الإجابة "جيسون برات"

على الرغم من أن Jasons إجابة يعمل, أنها لا تعمل إلا إذا كان أحد يريد لإضافة وظيفة إلى فئة.لم يكن العمل بالنسبة لي عندما حاولت تحديث القائمة بالفعل طريقة من .py source code file.

استغرق مني منذ مدة طويلة لإيجاد الحل ، ولكن الحيلة تبدو بسيطة...1.st استيراد التعليمات البرمجية من ملف التعليمات البرمجية المصدر 2.nd القوة تحديث 3.طريق استخدام أنواع.FunctionType(...) لتحويل المستوردة لا بد الأسلوب إلى وظيفة يمكنك أيضا تمرير المتغيرات العالمية الحالية ، reloaded الطريقة سيكون في مساحة الاسم 4.ال الآن يمكنك الاستمرار كما اقترح "جيسون برات" باستخدام أنواع.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

ما جيسون نشرت برات هو الصحيح.

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

كما يمكنك أن ترى الثعبان لا تنظر ب() أي مختلفة من().في بيثون جميع الأساليب هي فقط المتغيرات التي يحدث أن تكون الوظائف.

إذا كان يمكن أن يكون من أي مساعدة أنا صدر مؤخرا مكتبة بيثون اسمه الغوريلا لجعل عملية القرد الترقيع أكثر ملاءمة.

باستخدام وظيفة needle() التصحيح وحدة اسمه guineapig يذهب على النحو التالي:

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

ولكن أيضا أن تأخذ الرعاية من أكثر إثارة للاهتمام حالات الاستخدام كما هو موضح في أسئلة وأجوبة من الوثائق.

رمز متاح على جيثب.

كان هذا السؤال فتح منذ سنوات ، ولكن هناك طريقة سهلة لمحاكاة ملزمة وظيفة إلى فئة سبيل المثال باستخدام الديكور:

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

هناك عند تمرير وظيفة سبيل المثال إلى الموثق الديكور ، فإنه سيتم إنشاء وظيفة جديدة ، مع نفس رمز الكائن الأول.ثم تعطى مثيل من فئة يتم تخزينها في سمة حديثا وظيفة.الديكور العودة (الثالث) وظيفة الاتصال تلقائيا نسخ وظيفة ، وإعطاء سبيل المثال كما المعلمة الأولى.

في الختام لك الحصول على وظيفة محاكاة انها ملزمة الصف سبيل المثال.ترك الوظيفة الأصلية دون تغيير.

أجد أنه من الغريب أن لا أحد يذكر أن كل من الأساليب المذكورة أعلاه يخلق دورة المرجعية بين وأضاف أسلوب سبيل المثال ، تسبب الكائن أن تكون مستمرة حتى جمع القمامة.كان هناك خدعة قديمة إضافة واصف من خلال توسيع فئة من وجوه:

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

def method(self):
   print 'hi!'


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

مع ذلك, يمكنك استخدام مؤشر النفس

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top