gpt4 book ai didi

Python mixin 扩展类属性

转载 作者:太空狗 更新时间:2023-10-30 00:02:56 26 4
gpt4 key购买 nike

试图弄清楚如何为 Django 管理命令编写一些 mixins 来包装BaseCommand.option_list 不会丢失当前类或任何继承类/mixin 的值。目标是避免在我的命令中执行 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

也许我还有一个,只是为了涵盖我有多个的情况。 mixins 都覆盖了 __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, e.g. "_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.
)

如果 mixin 对 option_list 属性使用相同的名称,我就会遇到冲突。有没有比在 mixin 中唯一命名 option_list 并覆盖 __getattribute__ 更简洁的方法来实现这个目标?

最佳答案

documentation中的建议是显式连接各种选项列表。也就是说,如果您想走这条路,我认为自定义元类是正确的方法。像这样的东西:

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 mixin 扩展类属性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22644800/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com