2008-09-15 25 views
8

Bir metaclass kullanarak bir sınıf için bir örnek yöntemini nasıl ekleyebilirim (evet metaclass kullanmam gerekir)?Metaclass yöntemini kullanarak yöntem ekleme

def bar(self): 
    print "bar" 

class MetaFoo(type): 
    def __new__(cls, name, bases, dict): 
     dict["foobar"] = bar 
     return type(name, bases, dict) 

class Foo(object): 
    __metaclass__ = MetaFoo 

>>> f = Foo() 
>>> f.foobar() 
bar 
>>> f.foobar.func_name 
'bar' 

Sorunum bazı kütüphane kod aslında Foo örneğinin 'bar' yöntemi bulmak için başarısız sonra FUNC_NAME kullanır ve olmasıdır: çalışmaların şu tür ama FUNC_NAME hala "foo" olacaktır. Ayrıca types.MethodType vardır

dict["foobar"] = types.FunctionType(bar.func_code, {}, "foobar") 

ama does'nt bu kullanmak için henüz var bir örneğini gerekir: Ben yapabilirdi. Burada birşeyleri kaçırıyor muyum?

>>> class Foo(): 
... def __init__(self, x): 
...  self.x = x 
... 
>>> def bar(self): 
... print 'bar:', self.x 
... 
>>> bar.func_name = 'foobar' 
>>> Foo.foobar = bar 
>>> f = Foo(12) 
>>> f.foobar() 
bar: 12 
>>> f.foobar.func_name 
'foobar' 

Şimdi foobar adında bir yöntemi olması Foo örneklerini bekleyen bir kütüphaneye Foo s geçmek serbesttir:

+0

Neden yöntemin adını değiştirmeye çalışıyorsunuz? dict [bar.func_name] = bar istediğini yerine getirmiyor mu? –

+0

İyi soru ... Özünde, dict'ta tanımlanan özniteliklere dayanarak yöntem adları oluşturuyordum, ancak yöntemlerin uygulamaları özdeşse bunun anlamsız olduğunu anlıyorum. –

cevap

15

dinamik MRO yararlanabilir ve yöntemler gerçek yöntemlerdir bu şekilde üsleri uzanan deneyin:

class Parent(object): 
    def bar(self): 
     print "bar" 

class MetaFoo(type): 
    def __new__(cls, name, bases, dict): 
     return type(name, (Parent,) + bases, dict) 

class Foo(object): 
    __metaclass__ = MetaFoo 

if __name__ == "__main__": 
    f = Foo() 
    f.bar() 
    print f.bar.func_name 
+2

'Çubuk' uygulamasına başvuran çeşitli yöntemler oluşturmak istersem ne olur? –

+0

Merhaba Aaron, iyi çalışıyor ancak Foo'dan miras alan yeni bir sınıf NewFoo oluşturmaya çalışırsanız MRO sorunları nedeniyle bir miras hatası alırsınız. Bu sorunu benzer bir yaklaşımla çözmeye çalıştım: https://github.com/tierratelematics/pypom_form/blob/refactor/pypom_form/meta.py#L111 ancak en iyi yaklaşım olup olmadığını bilmiyorum. Bunu yapmak için daha pythonic bir yolu var. Python 3'te de iyi çalışmalı. –

2

Ben ne yapmak istiyorum bu olduğunu düşünüyorum.

Ne yazık ki, (1) Metasınıfı nasıl kullanacağımı bilmiyorum ve (2) Sorunuzu doğru okuduğumu bilmiyorum ama umarım bu yardımcı olur.

Not: func_name yalnızca Python 2.4 ve üstü sürümlerde atanabilir.

İlgili konular