假设我有以下课程
class Parent(object):
Options = {
'option1': 'value1',
'option2': 'value2'
}
一个名为Child
的子类class Child(Parent):
Options = Parent.Options.copy()
Options.update({
'option2': 'value2',
'option3': 'value3'
})
我希望能够在子类中覆盖或添加选项。我正在使用的解决方案。但我确信有更好的方法。
修改
我不想将选项添加为类属性,因为我有其他类属性不是选项,我更喜欢将所有选项保存在一个位置。这只是一个简单的例子,实际代码比这更复杂。
答案 0 :(得分:21)
在语义上等同于你的代码,但可以说是更整洁:
class Child(Parent):
Options = dict(Parent.Options,
option2='value2',
option3='value3')
请记住,“没有大括号的生活会更好”,并且通过明确地调用dict
,您通常可以避免使用大括号(以及类似于常量标识符的字符串的附加引号)。
有关详细信息,请参阅http://docs.python.org/library/stdtypes.html#dict - 关键位是“如果在位置参数和关键字参数中都指定了键,则保留与关键字关联的值”,即关键字args 覆盖位置arg中的键值关联,就像update
方法允许你覆盖它们一样。)
答案 1 :(得分:8)
一种方法是使用dict的关键字参数来指定其他键:
Parent.options = dict(
option1='value1',
option2='value2',
)
Child.options = dict(Parent.options,
option2='value2a',
option3='value3',
)
如果你想获得更好的,那么使用描述符协议你可以创建一个封装查找的代理对象。 (只需将所有者.__ mro__从owner属性转到__get __(self,instance,owner)方法)。甚至更高级,进入可能不是一个好主意的领域,元类/类装饰者。
答案 2 :(得分:6)
在仔细考虑之后,感谢@SpliFF的建议,这就是我想出来的:
class Parent(object):
class Options:
option1 = 'value1'
option2 = 'value2'
class Child(Parent):
class Options(Parent.Options):
option2 = 'value2'
option3 = 'value3'
我仍然愿意接受更好的解决方案。
答案 3 :(得分:4)
为什么不直接使用类属性?
class Parent(object):
option1 = 'value1'
option2 = 'value2'
class Child(Parent):
option2 = 'value2'
option3 = 'value3'
答案 4 :(得分:2)
class ParentOptions:
option1 = 'value1'
option2 = 'value2'
class ChildOptions(ParentOptions):
option2 = 'value2'
option3 = 'value3'
class Parent(object):
options = ParentOptions()
class Child(Parent):
options = ChildOptions()
答案 5 :(得分:2)
这是一种使用元类
的方法class OptionMeta(type):
@property
def options(self):
result = {}
for d in self.__mro__[::-1]:
result.update(getattr(d,'_options',{}))
return result
class Parent(object):
__metaclass__ = OptionMeta
_options = dict(
option1='value1',
option2='value2',
)
class Child(Parent):
_options = dict(
option2='value2a',
option3='value3',
)
print Parent.options
print Child.options