PEP 585 —— 标准集合中的类型提示泛型声称在 Python 3.7 和 3.8 下都具有标准from __future__ import annotations序言的可用性。尤其:
对于仅限于类型注释的用例,带有
annotationsfuture-import(自 Python 3.7 起可用)的Python 文件可以参数化标准集合,包括内置函数。
从 Python 3.7 开始,
from __future__ import annotations使用时,函数和变量注释可以直接参数化标准集合。例子:
from __future__ import annotations
def find(haystack: dict[str, list[int]]) -> int:
...
Run Code Online (Sandbox Code Playgroud)
虽然上面的玩具示例在技术上进行了解析,但仅此而已。在 Python 3.7 或 3.8 下尝试在运行时实际使用参数化的内置集合总是会引发可怕的TypeError: 'type' object is not subscriptable异常:
>>> def find(haystack: dict[str, list[int]]) -> int: pass
>>> print(find.__annotations__)
{'haystack': 'dict[str, list[int]]', 'return': 'int'}
>>> eval(find.__annotations__['haystack'])
TypeError: 'type' object is not subscriptable …Run Code Online (Sandbox Code Playgroud) 我从 Typescript 中知道了一个概念,称为“受歧视的联合”。这是你放置 2 个结构体(类等)的地方,并且类型是根据结构体的值决定的。我正在尝试通过Pydantic验证在FastAPI中实现类似的目标。我可以收到两种不同的请求负载。是其中之一还是另一个取决于变量。如果是,则应由 验证,如果是,则应由 验证。我该如何实现这一目标?找不到任何其他解决方案。accountTypecreativeRegistrationPayloadCreativebrandRegistrationPayloadBrand
问题是它要么返回
unexpected value; permitted: 'creative' (type=value_error.const; given=brand; permitted=('creative',))
或者它根本不起作用。
class RegistrationPayloadBase(BaseModel):
first_name: str
last_name: str
email: str
password: str
class RegistrationPayloadCreative(RegistrationPayloadBase):
accountType: Literal['creative']
class RegistrationPayloadBrand(RegistrationPayloadBase):
company: str
phone: str
vat: str
accountType: Literal['brand']
class A(BaseModel):
b: Union[RegistrationPayloadBrand, RegistrationPayloadCreative]
def main():
A(b={'first_name': 'sdf', 'last_name': 'sdf', 'email': 'sdf', 'password': 'sdfds', 'accountType': 'brand'})
if __name__ == '__main__':
main()
Run Code Online (Sandbox Code Playgroud) 我有两个带有注释/类型提示的类。
第一个工作没有任何问题:
from typing import TYPE_CHECKING
if TYPE_CHECKING:
from bunyamin.models.exchange import Exchange
class Kline:
def read_klines(exchange: Exchange):
pass
Run Code Online (Sandbox Code Playgroud)
第二个确实很相似:
from typing import TYPE_CHECKING
if TYPE_CHECKING:
from bunyamin.models.timeframe import Timeframe
def normalize_dt(dt: datetime, timeframe: Timeframe) -> datetime: # -> This line raises NameError
pass
Run Code Online (Sandbox Code Playgroud)
但提出NameError: name 'Timeframe' is not defined。
我知道我可以使用字符串(如'Timeframe')而不是类本身,但据我所知这不是预期的行为。我缺少什么?
我使用的 Python 版本是 3.8.2(如果相关的话)。
编辑:
当我试图隔离问题时,我省略了所有“看似不相关”的导入。但第一个文件实际上包含from __future__ import annotations在顶部,这使得它可以工作。详情请参阅第一个答案。
是否typing.TypedDict允许额外的钥匙?如果某个值具有 TypedDict 定义中不存在的键,该值是否会通过类型检查器?
使用以下示例:
from typing import Callable, Generic, Type, TypeVar
ThetaType = TypeVar('ThetaType', bound=int)
XType = TypeVar('XType', bound=int)
class IteratedFunction(Generic[ThetaType, XType]):
def find_fixed_point(self,
theta: ThetaType,
x_init: XType) -> XType:
return x_init
def combinator(
iterated_function_cls: Type[
IteratedFunction[ThetaType, XType]]) -> Callable[
[IteratedFunction[ThetaType, XType]], XType]:
old_find_fixed_point = iterated_function_cls.find_fixed_point
def new_find_fixed_point(
iterated_function: IteratedFunction[ThetaType, XType],
theta: ThetaType,
x_init: XType) -> XType:
return old_find_fixed_point(iterated_function, theta, x_init)
return new_find_fixed_point
Run Code Online (Sandbox Code Playgroud)
MyPy 说:
a.py:25: error: Incompatible return value type (got "XType", expected "XType")
a.py:25: error: Argument 1 has incompatible type "IteratedFunction[ThetaType, …Run Code Online (Sandbox Code Playgroud) 我想了解是否typing仍然需要该软件包?
如果在 Python 3.8 中我这样做:
from typing import Any, Dict
my_dict = Dict[str, Any]
Run Code Online (Sandbox Code Playgroud)
现在,在通过 PEP 585 的 Python 3.9 中,现在首选使用集合的内置类型,因此:
from typing import Any
my_dict = dict[str, Any]
Run Code Online (Sandbox Code Playgroud)
我是否仍然需要使用typing.Any或者是否有一个我找不到的内置类型来替换它?
在键入注释字符串、文本或 str 时应该使用什么?使用时有什么区别?
例如:
from typing import Text
def spring(a: Text) -> Text:
return a.upper()
Run Code Online (Sandbox Code Playgroud)
或者
def spring(a: str) -> str:
return a.upper()
Run Code Online (Sandbox Code Playgroud) 正如您在PEP 526中看到的,我们可以使用 ClassVar 字定义静态变量类。像下面这样
class Starship:
stats: ClassVar[dict[str, int]] = {} # class variable
damage: int = 10 # instance variable
Run Code Online (Sandbox Code Playgroud)
正如您在PEP 591中看到的另一个打字功能,我们可以使用 Final word 定义常量(只读)变量,如下所示
class Connection:
TIMEOUT: Final[int] = 10
Run Code Online (Sandbox Code Playgroud)
我的问题是如何组合这两个词来表示我的类静态变量是 Final?
例如下面的代码有效吗?
class Connection:
TIMEOUT: Final[ClassVar[int]] = 10
Run Code Online (Sandbox Code Playgroud) 我有以下代码:
def extract_table_date(bucket_path: str) -> str:
event_date = re.search(r"date=([^/]+)", bucket_path)
return event_date.group(1)[0:10].replace("-", "")
Run Code Online (Sandbox Code Playgroud)
mypy 在最后一行抛出错误:
“Optional[Match[str]]”的“None”项没有属性“group”
我想我可以通过为 分配一个类型来解决这个问题event_date,我可以:
from typing import Match
def extract_table_date(bucket_path: str) -> str:
event_date: Match = re.search(r"date=([^/]+)", bucket_path)
return event_date.group(1)[0:10].replace("-", "")
Run Code Online (Sandbox Code Playgroud)
但 mypy 现在在函数的第一行抛出另一个错误:
赋值中的类型不兼容(表达式的类型为“Optional[Match[Any]]”,变量的类型为“Match[Any]”)
我真的不知道如何通知 mypy 结果不是可选的,但尽管如此,我还是遵循了可选类型和 None 类型的建议,添加了断言:
from typing import Match
def extract_table_date(bucket_path: str) -> str:
assert bucket_path is not None
event_date: Match = re.search(r"date=([^/]+)", bucket_path)
return event_date.group(1)[0:10].replace("-", "")
Run Code Online (Sandbox Code Playgroud)
但 mypy 仍然引发相同的错误。
我尝试通过更改定义的类型来修复event_date:
from typing import Match, …Run Code Online (Sandbox Code Playgroud) mypy版本0.910
考虑
d = {
'a': 'a',
'b': {
'c': 1
}
}
d['b']['d'] = 'b'
Run Code Online (Sandbox Code Playgroud)
将其提供给mypy结果
error: Unsupported target for indexed assignment ("Collection[str]")
Run Code Online (Sandbox Code Playgroud)
mypy放置推断错误类型的一侧d(它显然不是字符串集合),添加一个非常基本的显式类型d修复此问题:
d: dict = {
... # same as above
}
Run Code Online (Sandbox Code Playgroud)
Success: no issues found in 1 source file
Run Code Online (Sandbox Code Playgroud)
我觉得这很奇怪。mypy绝对应该能够推断出这d是一个没有d: dict.
python ×10
python-typing ×10
mypy ×4
python-3.x ×4
type-hinting ×3
annotations ×2
fastapi ×1
pep585 ×1
pydantic ×1
python-3.8 ×1
python-3.9 ×1
string ×1
validation ×1