在子类中扩展类属性的简洁方法

时间:2009-05-25 16:28:54

标签: python

假设我有以下课程

class Parent(object):
    Options = {
        'option1': 'value1',
        'option2': 'value2'
    }

一个名为Child

的子类
class Child(Parent):
   Options = Parent.Options.copy()
   Options.update({
        'option2': 'value2',
        'option3': 'value3'
   })

我希望能够在子类中覆盖或添加选项。我正在使用的解决方案。但我确信有更好的方法。


修改

我不想将选项添加为类属性,因为我有其他类属性不是选项,我更喜欢将所有选项保存在一个位置。这只是一个简单的例子,实际代码比这更复杂。

6 个答案:

答案 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