简体   繁体   English

使用Super设置父类属性

[英]Setting Parent Class Attributes with Super

Can you set parent class attributes using super() in python 2.7? 您可以在python 2.7中使用super()设置父类属性吗? I would expect the following code to work, but it does not: 我希望以下代码可以工作,但不能:

class A(object):
    val_a = 1

class B(A):
    val_b = 2

    def set_a(self, val):
        super(B,self).__class__.val_a = val

b = B()

b.set_a(3)

It gives the following error: 它给出以下错误:

TypeError: can't set attributes of built-in/extension type 'super'

Is there a correct way to do this? 有正确的方法吗?

Can you set static class attributes using super() in python 2.7? 您可以在python 2.7中使用super()设置静态类属性吗?

No. 没有。

I would expect the following code to work, but it does not 我希望下面的代码能工作,但是不能

First, __class__ actually gets special-cased by super , to return the super instance's class, rather than performing the MRO search super usually does. 首先, __class__实际上被super特殊化,以返回super实例的类,而不是通常执行super的MRO搜索。

Second, there's no B.__dict__['__class__'] entry for super to bypass, so even if __class__ wasn't special-cased, it'd still be B instead of A . 其次,没有B.__dict__['__class__']条目可以绕开super ,因此,即使__class__不是特殊情况,它仍然是B而不是A

Third, if you want to refer specifically to class A , rather than whatever happens to come next in self 's MRO, you should just refer to A directly. 第三,如果要专门引用A类,而不是self的MRO中接下来发生的任何事情,则应直接引用A


Long story short: use A , not super . 长话短说:使用A而不是super

Reference A.val_a directly. 直接引用A.val_a val_a in this case is a "static" variable, not an "attribute" of an object instance. 在这种情况下, val_a是“静态”变量,而不是对象实例的“属性”。

The super call tries to get the object of self instance, and thus access to attribute super(B, self).val_a will fail. super调用尝试获取self实例的对象,因此对属性super(B, self).val_a将失败。

class A(object):
    val_a = 1

class B(A):
    val_b = 2

    def set_a(self, val):
        A.val_a = val 

b = B()
b.set_a(3)

print b.val_a

You can't do it with super() , but you can search through base classes of the subclass and do it that way. 您不能使用super()来做到这一点,但是可以在子类的基类中进行搜索并以这种方式进行。

Here's what I mean: 这就是我的意思:

class Other(object):
    val_a = 42

class A(Other):
    val_x = 1

    def __str__(self):
        return '{}(val_a={})'.format(self.__class__.__name__, self.val_a)

class B(A):
    val_b = 2

    def set_a(self, val):
        for cls in self.__class__.__mro__[1:]:
            try:
                object.__getattribute__(cls, 'val_a')
            except AttributeError:
                continue
            print('Updating class: {}'.format(cls.__name__))
            cls.val_a = val
            break
        else:
            raise RuntimeError("Can't find a base class with attribute 'val_a'")

b = B()
print(b)  # -> B(val_a=1)                     # B(val_a=42)
print('Other.val_a: {}'.format(Other.val_a))  # Other.val_a: 42
print('A.val_a: {}'.format(A.val_a))          # A.val_a: 42
print('B.val_a: {}'.format(B.val_a))          # B.val_a: 42
print('')
b.set_a(3)                                    # Updating class: Other
print('')
print(b)                                      # B(val_a=3)
print('Other.val_a: {}'.format(Other.val_a))  # Other.val_a: 3
print('A.val_a: {}'.format(A.val_a))          # A.val_a: 3
print('B.val_a: {}'.format(B.val_a))          # B.val_a: 3

According to your code you are trying to make the change for the instance. 根据您的代码,您尝试对实例进行更改。 Then, the function set_a needs to be as below. 然后,函数set_a需要如下所示。

class B(A):
    val_b = 2

    def set_a(self, val):
        self.val_a = val

But if you need the change to be applicable for the class level, you can use a class method and you can't use super() 但是,如果您需要使更改适用于类级别,则可以使用类方法,而不能使用super()

class B(A):
    val_b = 2

    @classmethod
    def set_a_class(cls, val):
        cls.val_a = val

B.set_a_class(5)
print B.val_a

b = B()
print b.val_a

will return 将返回

5 5

5 5

See Static variable inheritance in Python 请参阅Python中的静态变量继承

class A(object):
    val_a = 1


class B(A):
    val_b = 2
    def set_a(self, val):
        type(self).val_a = val


b1 = B()
b1.set_a(3)
b2 = B()
b2.set_a(4)
print type(b1).val_a
print type(b2).val_a
print A.val_a
print B.val_a

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM