代码之家  ›  专栏  ›  技术社区  ›  Nadia Alramli

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

  •  16
  • Nadia Alramli  · 技术社区  · 15 年前

    假设我有下面的课

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

    以及一个名为child的子类

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

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


    编辑

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

    6 回复  |  直到 14 年前
        1
  •  8
  •   Ants Aasma    15 年前

    一种方法是将关键字参数用于dict以指定其他键:

    Parent.options = dict(
        option1='value1',
        option2='value2',
    )
    
    Child.options = dict(Parent.options,
        option2='value2a',
        option3='value3',
    )
    

    如果您想变得更漂亮,那么使用描述符协议,您可以创建一个代理对象来封装查找。(只需将owner.u mro_uuuu从owner属性移动到u get_uuu(self,instance,owner)方法)。或者甚至更幻想,跨入可能不是好主意的领域,元类/类装饰师。

        2
  •  21
  •   Alex Martelli    15 年前

    在语义上相当于您的代码,但可以说整洁:

    class Child(Parent):
       Options = dict(Parent.Options,
          option2='value2',
          option3='value3')
    

    记住,“没有牙套生活会更好”,并且通过打电话 dict 显式地,您通常可以避免使用大括号(以及在像字符串一样是常量标识符的键周围加引号)。

    http://docs.python.org/library/stdtypes.html#dict 有关详细信息,键位为“如果在位置参数和关键字参数中都指定了键,则保留与关键字关联的值”,即关键字参数 重写 位置参数中的键值关联,就像 update 方法允许您重写它们)。

        3
  •  6
  •   Nadia Alramli    15 年前

    在考虑了更多之后,感谢@spliff的建议,这就是我想到的:

    class Parent(object):
        class Options:
            option1 = 'value1'
            option2 = 'value2'
    
    
    class Child(Parent):
        class Options(Parent.Options):
            option2 = 'value2'
            option3 = 'value3'
    

    不过,我仍然愿意接受更好的解决方案。

        4
  •  4
  •   Jason Baker    15 年前

    为什么不直接使用类属性呢?

    class Parent(object):
        option1 = 'value1'
        option2 = 'value2'
    
    class Child(Parent):
        option2 = 'value2'
        option3 = 'value3'
    
        5
  •  2
  •   SpliFF    15 年前
    class ParentOptions:
      option1 = 'value1'
      option2 = 'value2'
    
    class ChildOptions(ParentOptions):
      option2 = 'value2'
      option3 = 'value3'
    
    class Parent(object):
      options = ParentOptions()
    
    class Child(Parent):
      options = ChildOptions()
    
        6
  •  2
  •   John La Rooy    14 年前

    下面是使用元类的方法

    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