2 回答

TA貢獻(xiàn)1784條經(jīng)驗(yàn) 獲得超9個(gè)贊
是否有處理這種情況的最佳做法?
通常,類變量用于此目的。
class FourLeggedAnimal():
number_of_legs = 4 # class variable
def __init__(self, name):
self.name = name
class Cat(FourLeggedAnimal):
def __init__(self, name):
super().__init__(name)
def claw_the_furniture(self):
for leg in range(self.number_of_legs):
print("scratch")
class Dog(FourLeggedAnimal):
def __init__(self, name):
super().__init__(name)
def run_in_sleep(self):
for leg in range(self.number_of_legs):
self.move_leg(leg)
def move_leg(i):
pass
請(qǐng)注意,即使這些類位于不同的文件中,該屬性也是父類公共 API 的一部分并且子類可以知道。此外,類名“FourLeggedAnimal”很好地傳達(dá)了腿的數(shù)量。

TA貢獻(xiàn)1829條經(jīng)驗(yàn) 獲得超6個(gè)贊
我的理解是最好不要有定義不透明的變量(這就是為什么最好避免 from x import *.
我認(rèn)為您可能誤解了此建議的來源。它甚至可能是不同建議的混合體。我將嘗試解釋我認(rèn)為可能是人們?cè)噲D傳達(dá)的潛在想法。
首先,人們普遍認(rèn)為from x import *
最好避免在 Python 中使用。這是因?yàn)樗棺x者很難找出名稱的來源,或者是否確實(shí)定義了名稱。它還混淆了一些代碼分析工具。這是(非內(nèi)置)名稱通常進(jìn)入頂級(jí)命名空間而不會(huì)出現(xiàn)在源代碼中并且易于搜索的唯一方法。就此建議而言,它僅適用于這種情況。如果您不能在對(duì)象上使用字段和方法,那么您根本無法編寫 Python 代碼,而且您通常有一個(gè)清晰的面包屑痕跡可以遵循。(此外,如果您使用類型注釋。)
但是,您可能還會(huì)想到封裝的原理。在面向?qū)ο蟮木幊讨校詈脤?em>接口與對(duì)象的實(shí)現(xiàn)分開。您可以使界面盡可能小、簡(jiǎn)單和清晰,并使用代碼隱藏實(shí)現(xiàn)對(duì)象。通過這種方式,您可以獨(dú)立地推理和更改實(shí)現(xiàn),并確信這樣做不會(huì)影響其他代碼。這個(gè)原則甚至適用于基類和子類——子類不應(yīng)該“知道”它不需要的關(guān)于基類的任何事情?,F(xiàn)在,修改變量,以及在較小程度上閱讀可修改的變量,需要非常了解基類對(duì)其值的期望、它們與其他狀態(tài)的關(guān)系以及它們何時(shí)可能/允許更改。依賴它們會(huì)使安全更改基類變得更加困難。
現(xiàn)在,Python 在這方面確實(shí)比其他一些語言具有更大的靈活性。在 Python 中,您可以無縫地將變量替換為屬性,從而將“讀取”和“設(shè)置”字段轉(zhuǎn)換為您可以根據(jù)需要實(shí)現(xiàn)的方法。在其他語言中,一旦子類開始使用基類公開的字段,就不可能重構(gòu)基類以刪除該字段或在訪問它時(shí)添加任何額外行為,除非您還更新所有子類。所以這有點(diǎn)不太重要。或者更確切地說,沒有特別的理由將字段與方法區(qū)別對(duì)待。
考慮到所有這些,問題就變成了——您的基類向其子類呈現(xiàn)的接口是什么?它是否支持他們?cè)O(shè)置以及讀取該字段?您能否在不使代碼更復(fù)雜的情況下減小兩個(gè)類之間接口的大小和復(fù)雜性?如果一個(gè)接口是只讀的,那么它更簡(jiǎn)單,更容易推理,如果它根本不涉及可變狀態(tài)則更是如此。在可能的情況下,基類不應(yīng)給子類任何不必要的機(jī)會(huì)來破壞其不變量。(即它是對(duì)其自身狀態(tài)的期望。)在 Python 中,這些事情通常是通過約定(例如,以下劃線開頭的字段和方法被認(rèn)為不是公共接口的一部分,除非另有說明)和文檔而不是通過語言特性來實(shí)現(xiàn)。
添加回答
舉報(bào)