簡體   English   中英

使用Super設置父類屬性

[英]Setting Parent Class Attributes with Super

您可以在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'

有正確的方法嗎?

您可以在python 2.7中使用super()設置靜態類屬性嗎?

沒有。

我希望下面的代碼能工作,但是不能

首先, __class__實際上被super特殊化,以返回super實例的類,而不是通常執行super的MRO搜索。

其次,沒有B.__dict__['__class__']條目可以繞開super ,因此,即使__class__不是特殊情況,它仍然是B而不是A

第三,如果要專門引用A類,而不是self的MRO中接下來發生的任何事情,則應直接引用A


長話短說:使用A而不是super

直接引用A.val_a 在這種情況下, val_a是“靜態”變量,而不是對象實例的“屬性”。

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

您不能使用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

根據您的代碼,您嘗試對實例進行更改。 然后,函數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

請參閱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