[英]Restricted generic type hint in Python
我想創建一個像這里這樣的工廠方法。
class A:
...
class B(A):
def f(self):
...
class C:
...
def factory(cls):
return cls()
但我想添加一些具有兩個要求的類型提示:
A
子類作為factory
參數。B
通過,它被正確地將檢測到factory(B)
是實例B
,即。 factory(B).f()
是允許的,而factory(A).f()
不是。 使用來自typing
模塊的Type
。
from typing import Type
class A:
...
class B(A):
def f(self):
...
class C:
...
def factory(cls: Type[A]):
return cls()
factory(A) # Ok
factory(B) # Ok
factory(C) # Fail
factory(A).f() # Fail
factory(B).f() # Fail -- Wrong!
這個正確地檢測到C
不應該作為factory
參數傳遞。 但是,類型檢查器不允許factory(B).f()
。
使用類型TypeVar
。
from typing import TypeVar, Type
T = TypeVar('T')
class A:
...
class B(A):
def f(self):
...
class C:
...
def factory(cls: Type[T]) -> T:
return cls()
factory(A) # Ok
factory(B) # Ok
factory(C) # Ok -- Wrong!
factory(A).f() # Fail
factory(B).f() # Ok
可以很好地推斷出factory(B).f()
很好,而factory(A).f()
不是。 但是,泛型沒有限制,即。 工廠(C)也可以。
向T
添加約束。
from typing import TypeVar, Type
class A:
...
class B(A):
def f(self):
...
class D(A):
...
class C:
...
T = TypeVar('T', A)
def factory(cls: Type[T]) -> T:
return cls()
factory(A) # Ok
factory(B) # Ok
factory(C) # Fail
factory(A).f() # Fail
factory(B).f() # Ok
這看起來很有希望,至少 PyCharm 可以正確處理所有情況。 但是對於實際使用而言,這種解決方案實際上是最糟糕的 - A single constraint is not allowed
出現A single constraint is not allowed
錯誤,但尚不清楚原因。 在 PEP 484 中,只有簡短的一行說“應該至少有兩個約束,如果有的話; 不允許指定單個約束。
對此有什么好的解決方案嗎? 我只有一些東西,比如添加一個“虛擬”類_A
,一個空白的A
子類,並將其作為另一個約束來擁有這樣的東西。
_A = NewType('_A', A)
T = TypeVar('T', A, _A)
def factory(cls: Type[T]) -> T:
return cls()
但我真的不認為這是一個很好的解決方案。
先感謝您!
使用TypeVar
用bound
似乎工作:
from typing import Type, TypeVar
class A:
...
class B(A):
def f(self):
...
class C:
...
AnyA = TypeVar("AnyA", bound=A)
def factory(cls: Type[AnyA]) -> AnyA:
return cls()
factory(A).f() # error: "A" has no attribute "f"
factory(B).f() # ok!
factory(C) # error: Value of type variable "AnyA" of "factory" cannot be "C"
...類型變量可以使用
bound=<type>
指定上限。 這意味着替換(顯式或隱式)類型變量的實際類型必須是邊界類型的子類
這看起來和你想要的完全一樣,所以你可以寫:
T = TypeVar('T', bound=A)
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.