在子类中扩展类属性的简洁方法
假设我有一个这样的类
class Parent(object):
Options = {
'option1': 'value1',
'option2': 'value2'
}
还有一个叫做 Child 的子类
class Child(Parent):
Options = Parent.Options.copy()
Options.update({
'option2': 'value2',
'option3': 'value3'
})
我想在子类中能够重写或者添加一些选项。我现在用的方法是有效的,但我觉得一定有更好的办法。
补充说明
我不想把选项作为类的属性添加,因为我还有其他的类属性不是选项,我更希望把所有的选项放在一个地方。这只是一个简单的例子,实际上代码要复杂得多。
6 个回答
6
经过进一步思考,再加上@SpliFF的建议,我想出了这个方案:
class Parent(object):
class Options:
option1 = 'value1'
option2 = 'value2'
class Child(Parent):
class Options(Parent.Options):
option2 = 'value2'
option3 = 'value3'
不过我还是欢迎更好的解决办法。
21
这段代码在功能上和你的代码是一样的,但看起来更整洁:
class Child(Parent):
Options = dict(Parent.Options,
option2='value2',
option3='value3')
记住,“生活没有大括号更美好”,通过明确调用 dict
,你通常可以避免使用大括号(还有那些围绕常量字符串的额外引号)。
想了解更多细节,可以查看这个链接:http://docs.python.org/library/stdtypes.html#dict。关键点是:“如果一个键同时在位置参数和关键字参数中被指定,那么关键字参数对应的值会被保留”,也就是说,关键字参数会覆盖位置参数中的键值对,就像 update
方法可以让你覆盖它们一样。
8
一种方法是使用关键字参数来给字典添加额外的键:
Parent.options = dict(
option1='value1',
option2='value2',
)
Child.options = dict(Parent.options,
option2='value2a',
option3='value3',
)
如果你想让事情更复杂一点,可以使用描述符协议来创建一个代理对象,这样可以封装查找的过程。具体来说,就是从拥有者的属性开始,沿着拥有者的__mro__(方法解析顺序)走到__get__(self, instance, owner)这个方法。更复杂的做法是使用 metaclasses(元类)或者类装饰器,但这可能不是个好主意。