我想對抽象類方法進行型別注釋,使其表現為建構式。例如在下面的代碼中,ElementBase.from_data它是一個抽象類方法建構式。
臨時檔案
from abc import abstractmethod, abstractclassmethod
import copy
from typing import TypeVar, Type
ElementT = TypeVar('ElementT', bound='ElementBase')
class ElementBase:
data: int
def __init__(self, data): self.data
#@abstractmethod
def get_plus_one(self: ElementT) -> ElementT:
out = copy.deepcopy(self)
out.data = self.data 1
return out
@abstractclassmethod
def from_data(cls: Type[ElementT], data: int) -> ElementT: # mypy error!!!
pass
class Concrete(ElementBase):
@classmethod
def from_data(cls, data: int) -> 'Concrete': # mypy error!!!
return cls(data)
但是,將 mypy 應用于此代碼會顯示以下錯誤。
tmp.py:18: error: The erased type of self "Type[tmp.ElementBase]" is not a supertype of its class "tmp.ElementBase"
tmp.py:23: error: Return type "Concrete" of "from_data" incompatible with return type <nothing> in supertype "ElementBase"
你有什么想法來解決這個錯誤嗎?另外,我特別困惑的是,部分get_plus_one不會導致錯誤,而只有部分abstractclassmethod會導致錯誤。
僅供參考,我想讓抽象方法建構式通用,因為我想靜態地確保ElementBase在呼叫from_data.
[編輯] 注釋掉abstractmethod
uj5u.com熱心網友回復:
看起來mypy不太懂abstractclassmethod裝飾器。自 Python 3.3 以來,該裝飾器已被棄用,因為abstractmethod和classmethod裝飾器已更新為可以很好地配合使用。如果您這樣做,我認為您的代碼將正常作業:
@classmethod
@abstractmethod
def from_data(cls: Type[ElementT], data: int) -> ElementT:
pass
它與您的型別檢查問題無關,但如果您希望 Python 強制執行類的抽象性,您可能還希望更改ElementBase為從元類繼承abc.ABC或顯式請求元類。abc.ABCMeta常規類不關心abstractmethod裝飾器,因此按照撰寫的方式,您將能夠實體化ElementBase(或者,如果它的__init__方法沒有不相關的問題,您也可以實體化)。
還有一個關于這種型別提示的外圍相關注釋...... PEP 673將添加typing.Self到 Python 3.11 中,這將是一種方便的方法來參考它被呼叫的物件的型別。它應該可以很好地與類方法一起使用,而無需您跳過任何障礙。有了它,您就可以撰寫這個更簡單的注釋版本:
@classmethod
@abstractmethod
def from_data(cls, data: int) -> Self:
pass
轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/430913.html
標籤:python-3.x 遗产 抽象类 我的 打字
上一篇:顫振中的forEach錯誤以顯示帶有來自firebase實時資料的串列視圖
下一篇:C 多型性:如何創建派生類物件
