我有一个带有属性Klass的类my_list。我有一个SubKlass的子类,在其中我想要一个类属性my_list,它是父类相同属性的修改版本:

class Klass():
    my_list = [1, 2, 3]


class SubKlass(Klass):
    my_list = Klass.my_list + [4, 5] # this works, but i must specify parent class explicitly
    #my_list = super().my_list + [4, 5] # SystemError: super(): __class__ cell not found
    #my_list = my_list + [4, 5] # NameError: name 'my_list' is not defined


print(Klass.my_list)
print(SubKlass.my_list)

因此,有没有一种方法可以在不指定其名称的情况下访问父类属性?

更新:

Python问题追踪器上有一个错误:http://bugs.python.org/issue11339。我们希望它在某个时候是solved

最佳答案

你不能

在Python中,类定义的工作方式如下。

  • 解释器看到class语句,后跟一段代码。
  • 它创建一个新的 namespace 并在该 namespace 中执行该代码。
  • 它使用生成的 namespace ,类名称,基类和元类(如果适用)调用内置的type
  • 它将结果分配给类的名称。

  • 在类定义中运行代码时,您不知道基类是什么,因此无法获取其属性。

    您可以做的是在定义类后立即修改该类。

    编辑:这是一个小类装饰器,您可以用来更新属性。想法是给它命名和一个函数。它遍历该类的所有基类,并使用该名称获取其属性。然后,它将使用从基类继承的值列表以及您在子类中定义的值来调用该函数。该调用的结果绑定(bind)到该名称。

    代码可能更有意义:
    >>> def inherit_attribute(name, f):
    ...     def decorator(cls):
    ...             old_value = getattr(cls, name)
    ...             new_value = f([getattr(base, name) for base in cls.__bases__], old_value)
    ...             setattr(cls, name, new_value)
    ...             return cls
    ...     return decorator
    ...
    >>> def update_x(base_values, my_value):
    ...    return sum(base_values + [my_value], tuple())
    ...
    >>> class Foo: x = (1,)
    ...
    >>> @inherit_attribute('x', update_x)
    ... class Bar(Foo): x = (2,)
    ...
    >>> Bar.x
    (1, 2)
    

    这个想法是您将x定义为(2,)中的Bar。然后,装饰者将浏览Bar的子类,找到它们的所有x,并与它们一起调用update_x。因此它将调用
    update_x([(1,)], (2,))
    

    它通过串联它们来组合它们,然后再次将其绑定(bind)回x。那有意义吗?

    关于python - 从子类主体访问父类属性,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/9760595/

    10-12 00:27
    查看更多