簡體   English   中英

強制python子類init使用子類變量,而不是父類

[英]Force python subclass init to use subclass variables, not parent class

在以下代碼中:

class A(object):
  VALUE = 1
  def __init__(self, value=VALUE):
    self.value = value

class B(A):
  VALUE = 2

我希望B()。值應該等於2,但是:

B().value = 1

是否有一種優雅的方法來定義一個類層次結構,其中子類只能聲明它們想要覆蓋的類變量並使它們成為實例變量的默認值? 我仍然希望允許在每個實例級別更改這些,例如。

b = B(value=3)

這是另一個默認參數問題。 關鍵是你寫的時候

def foo(value=VALUE):

函數內部的代碼被編譯並成為一個函數對象。 就在這個時候 - 而不是在通話時間! - 存儲默認參數。 因此,當您定義B ,為時已晚: foo的默認值已經設置,更改VALUE將不會產生任何影響。

如果這看起來很奇怪,假設foo是一個全局函數:

default = 3
def foo(x=default): pass

然后任何其他代碼,任何地方,可以搞砸了foo

global default
default = 4

這可以說是令人困惑的。


要強制在運行時完成查找而不是編譯時間,您需要將它們放在函數中:

def foo(value=None):
    self.value = self.VALUE if value is None else value

或(不完全相同但更漂亮)

self.value = value or self.VALUE

(這是不同的,因為它將任何 'falsy'值視為哨兵 - 即0[]{}等都將被VALUE覆蓋。)


編輯:@mgilson指出了另一種方法:

def foo(**kwargs):
    self.value = kwargs.get("value", self.VALUE)

這更簡潔,因為它不需要你創建一個sentinel值(如Noneobject() ,但它確實從根本上改變了foo的參數規范,因為現在它將接受任意關鍵字參數。你的調用。

不應在func聲明行中定義默認值,否則,當python讀取此行時,默認值將被聚焦,無論您稍后更改VALUE,默認值都不會更改。

您可以按如下方式編寫它:

class A:
    VALUE = 1
    def __init__(self, value=None):
        if value is None:
            value = self.VALUE
        self.value = value

class B(A):
    VALUE = 2

print(A().value)
print(B().value)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM