使用Super设置父类属性

时间:2017-01-31 17:26:36

标签: python python-2.7

你能在python 2.7中使用super()设置父类属性吗?我希望以下代码可以工作,但它不会:

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)

它出现以下错误:

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

有没有正确的方法呢?

5 个答案:

答案 0 :(得分:2)

  

你能在python 2.7中使用__class__设置静态类属性吗?

没有

  

我希望以下代码可以正常工作,但它不会

首先,super实际上由super提供特殊内容,以返回super实例的类,而不是通常执行MRO搜索B.__dict__['__class__']

其次,super没有__class__条目可以绕过,所以即使B不是特殊情况,它仍然是A而不是A {1}}。

第三,如果你想特别提到班级self,而不是A的MRO中接下来发生的事情,你应该直接引用A

长话短说:使用super,而不是{{1}}。

答案 1 :(得分:1)

直接引用A.val_a。在这种情况下,val_a是一个"静态"变量,而不是"属性"一个对象实例。

super调用尝试获取自我实例的对象,因此对属性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

答案 2 :(得分:1)

您无法使用super()执行此操作,但您可以搜索子类的基类并按此方式执行。

这就是我的意思:

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

答案 3 :(得分:0)

根据您的代码,您正尝试对实例进行更改。然后,函数set_a需要如下所示。

class B(A):
    val_b = 2

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

但是,如果您需要将更改应用于班级,则可以使用班级方法,但不能使用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

将返回

  

5

     

5

答案 4 :(得分:0)

请参阅Static variable inheritance in 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