![](/img/trans.png)
[英]Can @classmethod be substituted using @staticmethod and returning an instance of the class?
[英]Type annotation for classmethod returning instance
我應該如何注釋一個返回cls
實例的@classmethod
? 這是一個不好的例子:
class Foo(object):
def __init__(self, bar: str):
self.bar = bar
@classmethod
def with_stuff_appended(cls, bar: str) -> ???:
return cls(bar + "stuff")
這將返回一個Foo
但更准確地返回調用它的Foo
的任何子類,因此使用-> "Foo"
進行注釋還不夠好。
訣竅是顯式向cls
參數添加注釋,結合TypeVar
,用於泛型和Type
,以表示類而不是實例本身,如下所示:
from typing import TypeVar, Type
# Create a generic variable that can be 'Parent', or any subclass.
T = TypeVar('T', bound='Parent')
class Parent:
def __init__(self, bar: str) -> None:
self.bar = bar
@classmethod
def with_stuff_appended(cls: Type[T], bar: str) -> T:
# We annotate 'cls' with a typevar so that we can
# type our return type more precisely
return cls(bar + "stuff")
class Child(Parent):
# If you're going to redefine __init__, make sure it
# has a signature that's compatible with the Parent's __init__,
# since mypy currently doesn't check for that.
def child_only(self) -> int:
return 3
# Mypy correctly infers that p is of type 'Parent',
# and c is of type 'Child'.
p = Parent.with_stuff_appended("10")
c = Child.with_stuff_appended("20")
# We can verify this ourself by using the special 'reveal_type'
# function. Be sure to delete these lines before running your
# code -- this function is something only mypy understands
# (it's meant to help with debugging your types).
reveal_type(p) # Revealed type is 'test.Parent*'
reveal_type(c) # Revealed type is 'test.Child*'
# So, these all typecheck
print(p.bar)
print(c.bar)
print(c.child_only())
通常,您可以不加注釋cls
(和self
),但是如果您需要引用特定的子類,則可以添加顯式注釋。 請注意,此功能仍處於試驗階段,在某些情況下可能存在錯誤。 您可能還需要使用從 Github 克隆的最新版本的 mypy,而不是 pypi 上可用的版本——我不記得該版本是否支持類方法的此功能。
為了完整起見,在 Python 3.7 中,您可以使用PEP 563中定義的postponed evaluation of annotations
,方法是在文件開頭導入from __future__ import annotations
。
然后對於您的代碼,它看起來像
from __future__ import annotations
class Foo(object):
def __init__(self, bar: str):
self.bar = bar
@classmethod
def with_stuff_appended(cls, bar: str) -> Foo:
return cls(bar + "stuff")
根據文檔,從 Python 3.11 開始,此導入將有效地自動進行。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.