2010-07-27 12 views
9

Python metaclasses karıştığı bir ezoterik sorum var. İstemci tarafı proxy'leri aracılığıyla rasgele Python sınıflarına erişmeyi kolaylaştıracak web-sunucu tarafı kodu için bir Python paketi oluşturuyorum. Proxy üreten kodum, API'mize eklemek istediğim tüm Python sınıflarının bir kataloğuna ihtiyaç duyuyor. Bu kataloğu oluşturmak için, sınıf oluşturma sürecine bir kanca koymak için __metaclass__ özel özniteliğini kullanıyorum. Özellikle, "yayımlanan" API sınıflarının tüm kendisi grup oluşturma ilgili bilgileri kaydetmek üzere ayarlanmış olan bir __metaclass__ sahip belirli bir temel sınıf, PythonDirectPublic, alt sınıf olacak. Şimdiye kadar çok iyi. Karmaşık olduğu yerde, PythonDirectPublic'un kendisinin bir üçüncü taraf sınıfından (enthought.traits.api.HasTraits) miras almasını istiyorum. Bu üçüncü taraf sınıfı da bir __metaclass__ kullanır.Python: metaclasses o kadar uzağa

Yani iki metaclasses yönetmenin doğru yolu nedir? Meta sınıfım Enthought'ın meta sınıfının bir alt sınıfı mı olmalı? Ya da geri döneceğim tip nesnesini almak için, metaclassın __new__ yöntemimin içerisindeki Enthought metaclass'ını çağırmalı mıyım? Ya da bu özel durumda kullanmak için başka bir mistik kâhin var mı?

cevap

5

Meta sınıfım, Enthought'ın meta sınıfının bir alt sınıfı mı olmalıdır?

O aslında tek seçeneğiniz olduğuna inanıyoruz. Türetilmiş bir sınıfın meta sınıfı, tüm tabanlarının meta sınıflarının bir alt sınıfı değilse, türetilmiş sınıf oluşturmaya çalıştığınızda Python bir TypeError atar. Eğer üçüncü taraf temel sınıf için metaclass tanımına erişimi yoksa Yani PythonDirectPublic için metaclass

class DerivedMetaClass(BaseMetaClass): 
    def __new__(cls, name, bases, dct): 
     # Do your custom memory allocation here, if any 

     # Now let base metaclass do its memory allocation stuff 
     return BaseMetaClass.__new__(cls, name, bases, dct) 

    def __init__(cls, name, bases, dct): 
     # Do your custom initialization here, if any 
     # This, I assume, is where your catalog creation stuff takes place 

     # Now let base metaclass do its initialization stuff 
     super(DerivedMetaClass, cls).__init__(name, bases, dct) 

gibi görünmelidir, sen enthought.traits.api.HasTraits.__metaclass__ ile BaseMetaClass yerini alabilir. Çok endişeli ama işe yarayacak.

1

Özellikle, "yayımlanan" API sınıflarının tüm Aksine başka metaclass ekleyerek yerine, yinelemeli PythonDirectPublic sonucunu kullanabilirsiniz,

PythonDirectPublic

belirli temel sınıf alt sınıf olacak. alt sınıflar().

+0

ben o belirli yöntem üzerinde herhangi bir belge bulamıyorum. HasTraits.trait_subclasses() kullanarak öneriyor musunuz? Bu, gerçekten de kataloğu oluşturmaya alternatif bir yaklaşım sağlayabilirdi. Dan Ellis aslında '__subclasses__' yöntemi ifade eder inanıyoruz –

+0

@DanMenes, nasıl kullanılacağını için [Bu cevap] (http://stackoverflow.com/a/3862957/396967) bakınız. – kynan

+0

@kynan Anladım. Bence bu da işe yarayacaktı. Bu koda baktığımdan birkaç sene olmasına rağmen, bütün kırışıklıkları hatırlamıyorum. –