2013-06-24 6 views
2

У меня есть базовый класс, от которого другие классы должны наследовать:Как объединить wxPython, abc и metaclass mixin?

class AppToolbar(wx.ToolBar): 
    ''' Base class for the Canary toolbars ''' 

    def __init__(self, *args, **kwargs): 
     super().__init__(*args, **kwargs) 

     # ... a few common implementation details that work as expected... 

     self._PopulateToolbar() 
     self.Realize() 

Базовый класс не (и не может) осуществлять _PopulateToolbar(); это должен быть абстрактный метод. Таким образом, я полагал, что с помощью abc был хороший план, поэтому я попытался это:

class AppToolbar(wx.ToolBar, metaclass=abc.ABCMeta): 
    # ... as above, but with the following added 
    @abc.abstractmethod 
    def _PopulateToolbar(): 
     pass 

Возможно, не удивительно, пытаясь запустить это привело к TypeError: metaclass conflict: the metaclass of a derived class must be a (non-strict) subclass of the metaclasses of all its bases. Я подумал: «О, да, я буду просто использовать подмешать»:

class PopulateToolbarMixin(metaclass=ABCMeta): 
    @abstractmethod 
    def _PopulateToolbar(self): 
     pass 

PopulateToolbarMixin.register(wx.ToolBar) 
PopulateToolbarMixin.register(AppToolbar) 

Без изменений: все тот же TypeError сообщений. Я подозреваю, что мне не хватает чего-то очевидного с использованием ABCMeta; это не похоже на ошибку, специфичную для wxPython. Что я делаю не так? Есть ли лучший способ подойти к одной и той же проблеме?

Редактировать: Мне было указано в разговоре с коллегой, что нельзя смешивать метаклассы. С wx.ToolBar, по-видимому, происходит от sip.wrappertype, похоже, что это невозможно. Что еще, все еще Pythonic способ обработки подхода «абстрактного метода» здесь?

ответ

1

В первом примере, где вы унаследовали от wx.ToolBar и abc.ABCMeta, вы не хотите AppToolbar быть подкласс из abc.ABCMeta, вы хотите AppToolbar быть экземпляр его. Попробуйте это:

class AppToolbar(wx.ToolBar, metaclass=abc.ABCMeta): 
    # ... as above, but with the following added 
    @abc.abstractmethod 
    def _PopulateToolbar(): 
     pass 

Хотя, глядя на это немного ближе, кажется, что вы не можете определить подкласс wx.Toolbar с abc.ABCMeta как его метакласса как wx.Toolbar является экземпляром метакласса кроме bultins.type. Тем не менее, вы можете получить абстрактное поведение из AppToolbar._PopulateToolbar:

class AppToolbar(wx.ToolBar): 
    def _PopulateToolbar(): 
     ''' This is an abstract method; subclasses must override it. ''' 

     raise NotImplementedError('Abstract method "_PopulateToolbar" must be overridden before it can be called.') 
+0

Mmm, good catch; это на самом деле то, что я изначально имел (забыл при повторном создании кода здесь). Увы, есть какой-то странный конфликт с wxPython, похоже, поскольку это не работает. –

+1

Тогда казалось бы, что wx.ToolBar не является прямым экземпляром типа, и в этом случае вам не повезло; насколько я знаю, нет хорошего способа совместить метаклассы в Python. –