我遇到了这个静态类型提示不匹配(使用 Pyright):
from __future__ import annotations
from typing import AnyStr, Iterable
def foo(i: Iterable[AnyStr]):
return i
def bar(i: Iterable[str] | Iterable[bytes]):
return i
def baz(i: Iterable[str | bytes]):
return i
def main():
s = ['a']
# makes sense to me
baz(foo(s)) # allowed
foo(baz(s)) # not allowed
# makes sense to me
baz(bar(s)) # allowed
bar(baz(s)) # not allowed
bar(foo(s)) # allowed
foo(bar(s)) # nope -- why?
Run Code Online (Sandbox Code Playgroud)
什么之间的区别Iterable[AnyStr]和Iterable[str] | Iterable[bytes]?
它们不应该是“等效的”吗?(除了AnyStr在上下文中引用单个一致类型)
更具体地说:键入提示以下内容的正确方法是什么?
import random …Run Code Online (Sandbox Code Playgroud) 我正在尝试匹配类型注释,例如int | str,并使用正则表达式替换将它们替换为 string Union[int, str]。
期望的替换(之前和之后):
str|int|bool->Union[str,int,bool]Optional[int|tuple[str|int]]->Optional[Union[int,tuple[Union[str,int]]]]dict[str | int, list[B | C | Optional[D]]]->dict[Union[str,int], list[Union[B,C,Optional[D]]]]到目前为止我想出的正则表达式如下:
r"\w*(?:\[|,|^)[\t ]*((?'type'[a-zA-Z0-9_.\[\]]+)(?:[\t ]*\|[\t ]*(?&type))+)(?:\]|,|$)"
Run Code Online (Sandbox Code Playgroud)
您可以在 Regex Demo 上尝试一下。它并没有真正按照我想要的方式工作。到目前为止我注意到的问题:
到目前为止,它似乎无法处理嵌套的 Union 条件。例如,int | tuple[str|int] | bool似乎会导致一场匹配,而不是两次匹配(包括内部 Union 条件)。
正则表达式似乎]最后消耗了不必要的东西。
可能是最重要的一个,但我注意到 Python 中的模块似乎不支持正则表达式子例程re。这是我想到使用它的地方。
这主要是为了支持Python 3.7+ 的PEP 604语法,该语法需要前向声明(例如声明为字符串)注释才能支持,否则内置类型不支持该|运算符。
这是我想出的示例代码:
r"\w*(?:\[|,|^)[\t ]*((?'type'[a-zA-Z0-9_.\[\]]+)(?:[\t ]*\|[\t ]*(?&type))+)(?:\]|,|$)"
Run Code Online (Sandbox Code Playgroud)
对于 3.10 之前的 Python 版本,我使用__future__import 来避免出现以下错误: …
Mypy 在这一行出错:
response = {'available_fields': []}
error: Need type annotation for 'response'
Run Code Online (Sandbox Code Playgroud)
当我添加响应是字典的愚蠢注释时,错误消失了:
response: typing.Dict = {'available_fields': []}
Run Code Online (Sandbox Code Playgroud)
所以,我对此有一些疑问。为什么愚蠢的注释会处理错误?如何调整 mypy(配置、选项等)而不担心没有注释的这一行?
Is there I way that I can annotate a function to ensure that an object being passed into the function has a certain method or attribute, but where I don't care about its actual type?
Pycharm internally uses a syntax that looks like {b} to indicate what methods/attributes it's inferred are required for the object, but that doesn't appear to be valid Python syntax:
def func(a: {b}): # Error
a.b = 1
Run Code Online (Sandbox Code Playgroud)
Is there a way to get the type …
有没有一种方法可以输入提示元素元组,而不必多次定义每个内部元素?
例子:
a = ((1, 2), (2, 3), (3, 4), (4, 5))
a: Tuple[Tuple[int, int], Tuple[int, int], Tuple[int, int], Tuple[int, int]]
Run Code Online (Sandbox Code Playgroud)
我正在寻找看起来像这样的东西
a: Tuple[5*Tuple[int, int]]
Run Code Online (Sandbox Code Playgroud)
否则我的代码会变得非常冗长,以便指示类似的内容(包含 5 个 4 个整数的元组的元组)
我有一个函数fun()接受 NumPy ArrayLike和“矩阵”,并返回 numpy 数组。
from numpy.typing import ArrayLike
import numpy as np
def fun(A, x: ArrayLike) -> np.ndarray:
return (A @ x) ** 2 - 27.0
Run Code Online (Sandbox Code Playgroud)
type对于有业务的实体,正确的是什么@?请注意,fun()也可以接受scipy.sparse;也许更多。
我有以下Foo基类,并且Bar继承自它:
class Foo:
def __init__(self, x: int) -> None:
self._x = x
def do(self, x: int) -> None:
pass
class Bar(Foo):
pass
Run Code Online (Sandbox Code Playgroud)
如果我重写Foo.doin Bar,并将参数的类型更改x为不兼容的内容(即不比 更通用int),那么 Mypy 将返回错误 - 这当然是我所期望的。
class Bar(Foo):
def do(self, x: str) -> None:
pass
Run Code Online (Sandbox Code Playgroud)
错误:
test.py:10: error: Argument 1 of "do" is incompatible with supertype "Foo"; supertype defines the argument type as "int"
test.py:10: note: This violates the Liskov substitution principle
test.py:10: note: See https://mypy.readthedocs.io/en/stable/common_issues.html#incompatible-overrides …Run Code Online (Sandbox Code Playgroud) python types liskov-substitution-principle mypy python-typing
在以下代码中some_method已通过元类添加:
from abc import ABC
from abc import ABCMeta
from typing import Type
def some_method(cls, x: str) -> str:
return f"result {x}"
class MyMeta(ABCMeta):
def __new__(mcs, *args, **kwargs):
cls = super().__new__(mcs, *args, **kwargs)
cls.some_method = classmethod(some_method)
return cls
class MyABC(ABC):
@classmethod
def some_method(cls, x: str) -> str:
return x
class MyClassWithSomeMethod(metaclass=MyMeta):
pass
def call_some_method(cls: Type[MyClassWithSomeMethod]) -> str:
return cls.some_method("A")
if __name__ == "__main__":
mc = MyClassWithSomeMethod()
assert isinstance(mc, MyClassWithSomeMethod)
assert call_some_method(MyClassWithSomeMethod) == "result A"
Run Code Online (Sandbox Code Playgroud)
然而,MyPy对此很不满意:
minimal_example.py:27: error: …Run Code Online (Sandbox Code Playgroud) 我试图理解类型注释,我有以下代码:
from typing import TypeVar
T = TypeVar('T')
class MyClass():
x: int = 10
def foo(obj: T) -> None:
print(obj.x)
foo(MyClass())
Run Code Online (Sandbox Code Playgroud)
当我运行 mypy 时,出现以下错误:
main.py:9: error: "T" has no attribute "x"
Found 1 error in 1 file (checked 1 source file)
Run Code Online (Sandbox Code Playgroud)
但是当我添加bound='MyClass'到时TypeVar,它没有显示任何错误。
这种行为的原因是什么?我尝试阅读文档,但没有找到任何关于bound设置为默认值时到底发生了什么的答案。
我的代码看起来像这样,BDW 运行良好,没有任何错误
from typing import Literal
def verify(word: str) -> Literal['Hello XY']:
a = 'Hello ' + word
return a
a = verify('XY')
Run Code Online (Sandbox Code Playgroud)
虽然,当我尝试使用 mypy 进行类型检查时,它会抛出错误error: Incompatible return value type (got "str", expected "Literal['Hello XY']")
注意:要执行类型检查mypy ./filename.py,只需在 pip 安装 mypy 后执行 。
另外,当我这样做时,类型检查工作正常
from typing import Literal
def verify(word: str) -> Literal['Hello XY']:
a = 'Hello ' + word
return 'Hello XY' #changed here
a = verify('XY')
Run Code Online (Sandbox Code Playgroud)
我缺少什么?
python ×10
type-hinting ×7
mypy ×5
annotations ×2
python-3.x ×2
covariance ×1
duck-typing ×1
liskov-substitution-principle ×1
metaclass ×1
numpy ×1
regex ×1
typechecking ×1
types ×1