Python mixin для расширения свойства класса

Попытка выяснить, как написать некоторые mixins для команды управления Django, которая будет обертывать BaseCommand.option_list не теряя значения текущего класса или любых унаследованных классов / mixins. Цель состоит в том, чтобы не выполнять в моих командах BaseCommand.option_list + MyCommonOptionMixin.option_list + MyOtherCommonOptionMixin.option_list + ( local command options ) команды).

Пример:

 class BaseCommmand(object): option_list = ( # Default options here. ) # Rest of BaseCommand code. 

Я определяю mixin с некоторыми общими вариантами:

 class MyCommonOptionMixin(object): option_list = ( # Some common option/options I wish to have available in many commands ) def __getattribute__(self, name): values = super(MyCommonOptionMixin, self).__getattribute__(name) if name == 'option_list': for option in self.option_list: if option not in values: values += option, return values 

Может быть, у меня есть еще один, просто чтобы покрыть тот случай, когда у меня много. __getattribute__ переопределяют __getattribute__

 class MyOtherCommonOptionMixin(object): option_list = ( # Maybe I have another mixin I want to define separately ) # Tried this, does not work with more than one mixin. def __getattribute__(self, name): values = super(MyOtherCommonOptionMixin, self).__getattribute__(name) if name == 'option_list': for option in self.option_list: if option not in values: values += option, return values # Works if the mixin defines the option_list under a different name, eg "_mymixin_options" # Then access at self._mymixin_options instead of self.option_list class MyCommand(MyCommonOptionMixin, MyOtherCommonOptionMixin, BaseCommand): option_list = BaseCommand.option_list + ( # Local defined options. ) 

Я столкнулся с конфликтом, если mixins используют одно имя для свойства option_list. Есть ли более чистый путь для достижения этой цели, чем однозначный выбор option_list внутри mixins и переопределение __getattribute__ ?

One Solution collect form web for “Python mixin для расширения свойства класса”

Совет в документации заключается в явной конкатенации различных списков опций. Тем не менее, если вы хотите пройти этот маршрут, я думаю, что обычным метаклассом является правильный подход. Что-то вроде:

 class CommandMetaclass(type): def __new__(mcl, name, bases, dct): # start with the option_list in the class we're creating # use set() to avoid duplicates option_list = set(dct.get('option_list', tuple())) # add the options from each base class for base in bases: option_list.update(base.__dict__.get('option_list', tuple())) # replace the original option_list with our combined version dct['option_list'] = tuple(option_list) return type.__new__(mcl, name, bases, dct) class MyCommand(MyCommonOptionMixin, MyOtherCommonOptionMixin, BaseCommand): __metaclass__ = CommandMetaclass option_list = ( # Local defined options. ) 
Python - лучший язык программирования в мире.