2011-05-31 17 views
12

Geçerli ve devralınan sınıflardan kısıtlamaları yalnızca bir sınıf yüklendiğinde (nesne başına değil!) Birleştirmek istiyorum.Python'da sınıflar (örnek olmayanlar) nasıl başlatılır?

class Validatable: 

    @classmethod 
    def _initialize_class_not_instance(cls): 
     # merge constraints from derived class and base classes 
     pass 

    __class__._initialize_class_not_instance() # doesn't work 
    # Validatable._merge_constraints() # doesn't work too 

sorun __class__ bu bağlamda yok ve Validatable çok tanımlanmamış olmasıdır:

class Domain(Validatable): 

    constraints = {...} 

ben her sınıf için bir kez çağrılmalıdır bir yöntem _initialize_class_not_instance tanımlanan Bunu yapmak için. Fakat kaçınmak istiyorum ki, API'mın kullanıcısı, başlatma yöntemini açık bir şekilde çağırmak zorundadır veya ek bir sınıf dekoratörü kullanmak zorundadır.

Sınıfı nasıl başlatacağınıza dair herhangi bir fikir var mı?

+0

Sınıflar ** örneklerdir, genellikle "type" örnekleridir, ancak @Ignacio, "type" özel bir alt sınıfının örnekleri olabileceğine işaret etmiştir. Python3 içinde kayıt için – Duncan

cevap

1

Bir sınıf dekoratörüyle ve kalıtım olmadan sona erdim. Bu dekoratör mevcut ve kalıtsal sınıfların kısıtlamaları birleştirir ve __init__ yöntemini geçersiz kılar: dekoratör sınıf (kısıtlamaları birleştirme ve yerleştirme yöntemlerine) ve örnekleri değiştirmeye sahip olduğu

def validatable(cls): 

    # merge constraints from derived class and base classes here ... 

    original_init = cls.__init__ 
    def init_to_insert(self, *args, **keywords): 
     self.errors = {} 
     original_init(self, *args, **keywords) 
    cls.__init__ = init_to_insert 
    return cls 

Bu, zaman çözümü için bir anahtardır.

16

Bir metaclass kullanın.

class MetaClass(type): 
    def __init__(cls, name, bases, d): 
    type.__init__(cls, name, bases, d) 
    cls.foo = 42 

class MyClass(object): 
    __metaclass__ = MetaClass 

print MyClass.foo 
+8

, 'MyClass (nesne, metaclass = MetaClass)' – ninjagecko

+0

Neden MetaClass'a ihtiyacınız var? Neden sadece "MyClass" tanımından sonra "MyClass.foo = 42" ifadesini koymadı? –

İlgili konular