2015-05-18 26 views
15

Çok fazla arama yaptıktan sonra, varolan örnek nesnelere bir bağlı yöntem veya ilişkisiz sınıf yöntemleri eklemenin birkaç yolu olduğunu fark ettim.Python'da varolan bir nesneye yöntem eklemek için herhangi bir zarif yol var mı?

Bu tür yöntemler, aşağıdaki kodun yaklaşan yaklaşımlarını içerir. Beni rahatsız edici kılan

import types 


class A(object): 
    pass 


def instance_func(self): 
    print 'hi' 

def class_func(self): 
    print 'hi' 

a = A() 

# add bound methods to an instance using type.MethodType 
a.instance_func = types.MethodType(instance_func, a)    # using attribute 
a.__dict__['instance_func'] = types.MethodType(instance_func, a) # using __dict__ 

# add bound methods to an class 
A.instance_func = instance_func 
A.__dict__['instance_func'] = instance_func 

# add class methods to an class 
A.class_func = classmethod(class_func) 
A.__dict__['class_func'] = classmethod(class_func) 

iki kez işlevin adını, instance_func veya class_func yazarak vardır.

İşlev adını bir daha yazmadan bir işlev veya örneğe varolan bir işlevi eklemenin basit bir yolu var mı?

Örneğin, A.add_function_as_bound_method(f) işlevi zaten __name__ niteliği sahip olduğundan örneğine veya sınıfa varolan işlev eklemek için uzak çok şık bir yol olacaktır.

cevap

43

Normalde, nesne sözlüklerinde saklanan işlevler, noktalı erişime baktığınızda otomatik olarak kenar tablolarına dönüşmez.

>>> from functools import partial 
>>> class Dog: 
     def __init__(self, name): 
      self.name = name 


>>> d = Dog('Fido') 
>>> e = Dog('Buddy') 
>>> def bark(self):     # normal function 
     print('Woof! %s is barking' % self.name) 

>>> e.bark = partial(bark, e)  # pre-bound and stored in the instance 
>>> e.bark()      # access like a normal method 
Woof! Buddy is barking 

Bu yöntem eklemek için bir biraz şık bir şekilde:

bir yöntem gibi ulaşılabilir, böylece fonksiyonu önceden bağlanan ve nesne sözlükte depolamak functools.partial kullanabilir, bahsedilen bu varolan bir nesneye (sınıfını değiştirmeye gerek kalmadan ve diğer mevcut nesneleri etkilemeden).

Takibi Comment için:

>>> add_method(e, bark) 
>>> e.bark() 
Woof! Fido is barking 
:

>>> def add_method(obj, func): 
     'Bind a function and store it in an object' 
     setattr(obj, func.__name__, partial(func, obj)) 

böyle kullanın:

Önceden bağlanmış işlev eklemek için bir yardımcı işlev kullanabilirsiniz tek bir adımdır

Bu, tam olarak neye ihtiyacınız olduğunu umar :-)

İlgili konular