2012-01-04 18 views
7

verir I have a aşağıdaki modeli ve soyut temel sınıfbir Django modeli, bir metaclass çatışmayı

import abc 
from django.db import models 


class AbstractBase(): 
    __metaclass__ = abc.ABCMeta 

    @abc.abstractmethod 
    def my_method(self): 
     return 


class MyModel(models.Model, AbstractBase): 
    @abc.abstractmethod 
    def my_method(self): 
     return 1 

Ama aşağıdaki hatayı alıyorum.

metaclass çatışma: Bir türetilmiş sınıfın metaclass tüm üsleri metaclasses bir (non-sıkı) alt sınıf olmalıdır

Ben burada açıklanan gibi Buradaki sorun (olduğunu düşünüyorum http://code.activestate.com/recipes/204197-solving-the-metaclass-conflict/) iki temel sınıfın iki farklı metasınıfı olduğundan, python alt nesne için hangi metaclassın kullanılacağına karar veremez.

bu çözmek için ben çocuk sınıf

abc.register(Child) 

kayıt kayıt yöntemiyle aşağıdaki çoklu kalıtım ve kullanımını kaldırıldı Ama maymun yama gibi görünüyor çünkü bu yaklaşım gerçekten sevmedim.

Bu sorunu çözmenin başka bir yolu var mı?

Model metaclass'ı açık bir şekilde Çocuk'a atayım ancak işe yaramadı. Kod yazarak çözmek için bir yol arıyorum. Bunun, sınıf yapılarımı değiştirerek çözülmesi gerektiğini düşünüyorum.

+0

Sanırım hem django hem de abc'nin şeylerini yapan yeni bir metaclass oluşturmak zorunda kalacaksınız, muhtemelen kendi meta sınıflarını sırayla, belki miras kullanarak arayacaksınız. – cha0site

+0

abs.register yöntemini kullanma konusunda hiçbir şey yoktur - bu durumlar için tam olarak tasarlanmıştır. BTW, Python yolu o şeyler düşünülür, bu yüzden nadiren _need_ arayüzleri ve böyle şeyler yapmalısınız - belki de işlerin statik dilde yapılmasıyla çok kısıtlısınızdır? – jsbueno

+0

@jsbueno - Haklı olabilirsiniz, ancak bir şekilde arayüz işlevselliğini uygulamanız gerekecek. İşte bir örnek implantasyon - https://gist.github.com/1559689. Bu işlevselliği python'da uygulamak için daha iyi bir yolu var mı? – yilmazhuseyin

cevap

2

dışında hem ABCMeta ve ModelBase, devraldığı yeni metaclass oluşturma veya ModelBase den ABCMeta kaynaklanan devralma yapmaktan, çok yapabileceğiniz yoktur. Bununla birlikte, muhtemelen farklı bir kayıt modeli uygun olabilir mi? Belkide contrib.admin.autodiscover gibi bir şey? Veya bir sınıf dekoratör? Veya .py dosyasının altındaki register adlı dosyanın uygun sınıflara (ör. for var in globals().values(): if isinstance(var, type) and issubclass(var, AbastractBase): register(var)) bağlandığı bir döngü mü?

Düzenle: D'oh. ABCMeta'un bir örnek olduğunu varsaydım, ABCMeta değil. Çok az uykuda StackOverflow'a göz attım.

+0

Bunun hakkında bir sonucum, abc'leri bir arabirim olarak kullanıyorum, abc.register kullanmalıyım. Gerçekten bir arayüz uygulamak için daha iyi bir yol olması gerektiğini düşünüyorum (http://www.python.org/dev/peps/pep-0245/). Onlar olmadan pythonun oo özellikleri bana çok zayıf geliyor. – yilmazhuseyin

+3

Bunun "Python'un OO'unu zayıflattığını" düşünüyorsanız, o zaman "güçlü OO gereklilikleri" hakkındaki anlayışınızın Python'un tasarımcılarınınkinden büyük ölçüde farklı olduğunu (ya da yazarken kasten "oo" yazdığınızı) öne sürebilirim. "statik tip kontrolü"?) –