我一直在将类型信息添加到程序包的.py文件中,以支持mypy针对程序包运行。除其他事项外,它允许为此第三方包装生成分类信息。
由于我的软件包必须与Python 2.7兼容,因此我在类型信息中使用了注释:
def __init__(self, s):
# type: (Text) -> None
Run Code Online (Sandbox Code Playgroud)
但是要运行mypy此命令,我需要输入以下内容:
from typing import Text, IO, BinaryIO, Union
Run Code Online (Sandbox Code Playgroud)
这会导致两个问题:
这在Python 3.5.0和3.5.1上不起作用,因为它有一个模块typing,但不包含Text。typing从PyPI 安装并不能解决该问题。(并且有些用户在该版本的Python上运行该软件包)。
这使我的软件包依赖于typing2.7 / 3.3 / 3.4安装,需要额外的下载和安装。
我Union定义了自己的类型:
StreamType = Union[BinaryIO, IO[str], StringIO]
StreamTextType = Union[Text, StreamType]
Run Code Online (Sandbox Code Playgroud)
该代码必须根据是否可用键入而有条件地执行。
对于第一个问题,由于我没有mypy在Python 3.5.0 / 1下运行,因此可以执行以下操作:
import sys
if sys.version_info < (3, 5, 0) and sys.version_info >= (3, 5, 2):
from typing import …Run Code Online (Sandbox Code Playgroud) 我写了一个代码python 3.5,看起来像这样:
from collections import namedtuple
attributes = ('content', 'status')
Response = namedtuple('Response', attributes)
Run Code Online (Sandbox Code Playgroud)
然后我运行mypy类型检查器来分析这段代码.mypy提出这个错误:
test.py:4:error:作为第二个参数的List或tuple literal
namedtuple()
我试图在attributes变量中添加一个类型注释:
from typing import Tuple
attributes = ('content', 'status') # type: Tuple[str, str]
Run Code Online (Sandbox Code Playgroud)
但它没有帮助修复引发的错误.
我该怎么做才能纠正这个错误?谢谢.
我想在类型存根中添加一个名为的集合类List,这实际上是内置函数的包装list。出于所有实际目的,您可以假设它看起来像这样:
# library.py
class List:
def __init__(self, *values):
self.values = values
Run Code Online (Sandbox Code Playgroud)
现在,在我的存根文件library.pyi中:
# library.pyi
from typing import Generic, TypeVar, Iterable
T = TypeVar('T')
class List(Generic[T]):
def __init__(self, *values: T) -> None: ...
Run Code Online (Sandbox Code Playgroud)
如果执行以下操作,我想输入失败:
# client.py
from library import List
def f() -> List[str]:
return List(*range(10))
Run Code Online (Sandbox Code Playgroud)
但是mypy client.py以0退出。此外,python client.py失败以TypeError: 'type' object is not subscriptable。
我的理解是类型提示对运行时没有任何影响。那显然是错误的。有人可以纠正我关于类型提示如何工作的心理模型吗?
而且,有什么可以得到我想要的(即mypy client.py失败)吗?
我有以下函数,给定形式的字符串'a-02/b-03/foobarbaz_c-04',它将提取a,b和c之后的数字。问题在于,就我的用例而言,输入字符串可能不包含c,因此将没有要提取的数字。
这是代码:
from typing import Tuple, Optional
def regex_a_b_c(name: str) -> Tuple[int, int, Optional[int]]:
a_b_info = re.search('a-(\d\d)/b-(\d\d)/', name)
a, b = [int(a_b_info.group(x)) for x in range(1, 3)]
c_info = re.search('c-(\d\d)', name)
if c_info:
c = int(c_info.group(1))
else:
c = None
return a, b, c
Run Code Online (Sandbox Code Playgroud)
我的问题是,尽管试图弄清楚最后一个返回参数是an Optional[int],但我还是不能让我的小子停止抱怨变量c。
我收到警告c =None说
分配中的类型不兼容(表达式的类型为None,变量的类型为int)
。我该如何解决这个问题?
我正在尝试定义一个自定义的通用 dict,它的键是 type T_key,值是 type T_val。
我还想对T_keyand施加约束T_val,这样T_key只能是类型AorB或它们的子类。
我该如何实现?
from typing import TypeVar, Generic
class A: ...
class B: ...
class Asub(A): ...
class Bsub(B): ...
T_key = TypeVar('T_key', A, B, covariant=True)
T_val = TypeVar('T_val', A, B, covariant=True)
class MyDict(Generic[T_key, T_val]): ...
w: MyDict[ A, B]
x: MyDict[ A, Bsub]
y: MyDict[Asub, B]
z: MyDict[Asub, Bsub]
Run Code Online (Sandbox Code Playgroud)
当我尝试检查这一点时,mypy 在x,y和 的注释上给出了错误z。只有注释w按预期工作。
generic.py:17: error: …Run Code Online (Sandbox Code Playgroud) 伟大的,考虑以下代码。
from abc import ABC, abstractmethod
class Interface(ABC):
@abstractmethod
def method(self) -> None:
pass
class A(Interface):
def method(self) -> None:
pass
class B(Interface):
def method(self) -> None:
pass
mapping = {'A': A, 'B': B}
# does NOT pass mypy checks
def create_map(param: str) -> Interface:
if param in mapping:
return mapping[param]()
else:
raise NotImplementedError()
# passes mypy checks
def create_if(param: str) -> Interface:
if param == 'A':
return A()
elif param == 'B':
return B()
else:
raise NotImplementedError()
Run Code Online (Sandbox Code Playgroud)
出于某种原因,create_if …
我在 Python 中有以下列表推导式:
from typing import cast
# everything is fine
print([value for value in [1, 2, 3, 4]])
# on the first "value": Expression type contains "Any" (has type "List[Any]")
print("{}".format([value for value in [1, 2, 3, 4]]))
# on the "cast": Expression type contains "Any" (has type "List[Any]")
print("{}".format([cast(int, value) for value in [1, 2, 3, 4]]))
Run Code Online (Sandbox Code Playgroud)
为什么使用format会导致 Mypy 返回错误?如您所见,我尝试使用强制转换,但仍然失败。
这个问题看起来很相似,但我的特殊情况很奇怪,因为只要我不使用该format函数,Mypy 似乎就可以了(但该函数始终没问题print)。
有什么我可以做的,不让带格式的行给我错误?(或者我应该只是# type: ignore他们?)
编辑:请注意,这似乎不仅仅是我的 Atom linter 的问题。我使用的是 …
有一个类扩展了另一个类并覆盖了一个返回迭代器的协程:
class Repository:
async def run(self, query: Query) -> AsyncIterator[int]:
...
class MyRepository(Repository):
async def run(self, query: Query) -> AsyncIterator[int]:
...
Run Code Online (Sandbox Code Playgroud)
运行 mypy 返回此错误:
error: Return type "AsyncIterator[int]" of "run" incompatible with return type "Coroutine[Any, Any, AsyncIterator[int]]" in supertype "Repository"
Run Code Online (Sandbox Code Playgroud)
协程的类型与普通函数一样,所以我不确定正确的方法是什么。
使用 ABC 类不会修复它:
class Repository(metaclass=ABCMeta):
@abstractmethod
async def run(self, query: Query) -> AsyncIterator[int]:
Run Code Online (Sandbox Code Playgroud) 我最近一直在潜入 MyPy 并从他们的文档中看到以下示例
from typing import TypeVar, SupportsAbs
T = TypeVar('T', bound=SupportsAbs[float])
def largest_in_absolute_value(*xs: T) -> T:
return max(xs, key=abs) # Okay, because T is a subtype of SupportsAbs[float].
Run Code Online (Sandbox Code Playgroud)
这表明可以使用 mypy,因此传入的泛型必须支持 abs 函数才能通过静态类型检查器。
但我不清楚这到底是如何工作的。例如,如果我可以指定一个类型必须支持的任何函数,或者该类型必须介于两者之间的范围,我就会发现这非常强大。
我的问题如下:有没有办法使用 bound 来支持任何随机函数要求?例如,类型必须支持len函数吗?(我怀疑这是可能的)
特定变量类型(即小于 10 个字符的字符串,或小于 100 的 int)的范围呢?(我怀疑这是不太可能的)
myunionA可以是整数或整数列表。我如何编写类型提示来反映这一点?
它尝试了以下代码并使用 mypy 对其进行了测试。最后一行失败 - 请参阅错误文本。
numbers: List[int]
myunionA: Union[int, List[int]]
myunionB: Union[int, List[int]]
numbers = [11, 22]
numbers[2] = 3
myunionA = 2
myunionB[2] = 22 # ERROR(mypy): Unsupported target for indexed assignment
Run Code Online (Sandbox Code Playgroud)
如何编写一个类型提示,让我分配一个整数或一个整数列表?
mypy ×10
python ×9
python-3.x ×4
generics ×3
type-hinting ×3
typing ×3
abc ×1
covariance ×1
list ×1
stub ×1
typeshed ×1
union ×1