該片段:
class Base:
def superclass_only(self)。
return 'yes'。
class Foo(Base)。
通過。
foo = Foo()
>>> foo.superclass_only()
是的
# Expection是引發錯誤的。
>>> foo.superclass_only()
回溯
...
AttributeError: 'Foo' object沒有屬性'superclass_only'。
如果我只想定義一個只屬于超類的方法,該怎么辦呢?
CodePudding
TL;DR:在方法名前加上__,以觸發Python的名稱混雜機制。
回答:
你通常不能這樣做:這不是繼承應該作業的方式。 如果你需要在 "子類 "中 "隱藏 "方法,你應該重新設計你的方法。
第一件事是使用命名慣例來表明方法是私有的,在Python中,我們通過在方法名稱中添加"_"前綴來做到這一點:這應該是向你的Foo類的用戶表明,保留的方法應該只由在Base中撰寫代碼的人使用,而不應該被打擾。
另一件事是想一想,在這種情況下,你是不是用組合比用繼承更好:如果你的Base類知道做Foo自己不能做的事情,你真的能說 "Foo物件也是Base物件 "嗎?(這就是繼承的意義)。
也許,更好的設計是:
class Base:
...
class Bar:
def method_foo_cant_do(...) 。
...
class Foo(Base)。
def __init__(self, ...) 。
self.bar = Bar()
...
最后,盡管不是為此而設計的,而是為了避免在復雜的層次結構中出現方法名沖突,Python 有一個 "名稱混淆 "機制,它將透明地把一個方法名改為包括類名的前綴。這將避免在子類中隨意使用該方法,并且更有力地表明它應該在 "基 "類中使用--但不會 "不惜一切代價 "地阻止它被呼叫。
我們的方法是簡單地在方法前加上兩個下劃線。在編譯時,Python 將方法翻譯成 f"_{class_name}__{method_name}",在方法宣告處以及在它被宣告的類中的所有參考中。所以 Foo.__superclass_only 不會到達 Base.__superclass_only,因為后者的名字已經被改成了 Base._Base__superclass_only:
class Base。
def __superclass_only(self):
return 'yes'。
class Foo(Base)。
通過。
而在互動式解釋器上:
在 [3]: f= Foo()
在 [4]: f.__superclass_only()
---------------------------------------------------------------------------
AttributeError Traceback (最近一次呼叫)
<ipython-input-4-19c8185aa9ad> in < module>
----> 1 f.__superclass_only()
但是它仍然可以通過使用轉換后的名稱達到。f._Base__superclass_only()就可以了。
Python 允許的另一件事是為一個給定的類定制檢索屬性的方式:類中屬性和方法的搜索是由每個類中的 __getattribute__ 方法執行的 (不要把它和 __getattr__ 弄混了,后者更簡單,只在沒有找到屬性的時候才會被擊中)。
重新實作__getattribute__容易出錯,而且很可能讓你比你開始的方式更糟糕,給定一個foo物件,我們仍然能夠通過以下方式呼叫superclass_only
Base.superclass_only(foo, ...)(即:從基類中檢索該方法作為一個非系結的方法(函式),并手動傳入foo實體,使其成為 "self "引數),而緩解這個問題需要你在元類上實作一個正確的__get_attribute__ -(而這最終還是可以被那些能夠閱讀源代碼的人繞開)
uj5u.com熱心網友回復:
你可以用一個裝飾函式來包裝這個只適用于超類的方法,這個裝飾函式可以根據方法的類名來驗證當前實體的類名,這個類名可以從方法的__qualname__屬性中得到:
def superclass_only(method)。
def wrapper(self, *args, **kwargs)。
if self.__class__.__name__ != method.__qualname__.split('. ')[-2]。
raise NotImplementedError
return method(self, *args, **kwargs)
return wrapper
因此,與:
class Base。
@superclass_only
def method(self)。
return 'yes'.
class Foo(Base)。
通過。
呼叫Base().method()回傳'yes',而呼叫Foo().method()引發NotImplementedError。
演示。https://replit.com/@blhsing/SpringgreenHonorableCharacters/a>
轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/313410.html
標籤:
上一篇:如何設計被不同程式使用的物件?
