假设我有一个函数do_something:
from typing import Sequence, Tuple, Dict
def do_something(argument: Sequence[Tuple[int, str]]):
pass
Run Code Online (Sandbox Code Playgroud)
假设我还有一个字典 ,D其键仅是ints,其值仅是strs:
D: Dict[int, str] = {1: 'a', 2: 'b', 3: 'c'}
Run Code Online (Sandbox Code Playgroud)
在 PyCharm 中,这将出色地通过类型检查器:
do_something(
((1, 'a'), (2, 'b'), (3, 'c'))
)
Run Code Online (Sandbox Code Playgroud)
但是,根据 PyCharm 的说法,尽管它产生的结果是相同的,但类型检查器却失败了:
do_something(tuple(D.items()))
Run Code Online (Sandbox Code Playgroud)
这是预期的行为吗——我在这里遗漏了什么吗?-- 或者这是 PyCharm 类型检查器的错误?
如果我输入插槽:
class Foo:
__slots__: Tuple[()] = tuple()
Run Code Online (Sandbox Code Playgroud)
然后,在严格模式下,mypy (0.812) 告诉我:
Incompatible types in assignment (expression has type "Tuple[<nothing>, ...]", variable has type "Tuple[]")
Run Code Online (Sandbox Code Playgroud)
我可以写:
__slots__: Tuple[()] = cast(Tuple[()], tuple())
Run Code Online (Sandbox Code Playgroud)
但这很丑陋。执行此操作的规范方法是什么?mypy 是什么意思Tuple[<nothing>, ...]?元组是不可变的,所以空元组肯定不应该是……没有任何变量的量……?
我遇到了以下代码的问题,至少根据 mypy 是这样的:
from multiprocessing import Pool
from typing import Tuple, TypeVar
T = TypeVar("T", int, str)
def do_something(a: T) -> Tuple[T, bool]:
# Something happening here...
return a, False
if __name__ == "__main__":
pool = Pool(processes=10)
nums = list(range(100000, 1000000))
for r in pool.imap_unordered(do_something, nums):
if r[1]:
print(f"Got {r[0]}")
Run Code Online (Sandbox Code Playgroud)
当我使用 mypy 检查它时,出现以下错误:
error: Argument 1 to "imap_unordered" of "Pool" has incompatible type "Callable[[T], Tuple[T, bool]]"; expected "Callable[[int], Tuple[T, bool]]"
Run Code Online (Sandbox Code Playgroud)
实际类型显然应该满足预期类型。我做错了什么还是 mypy 或 multiprocessing.Pool 中的错误?
预先感谢您的任何评论。
我有一个代表标准化内存量的类。
class MemoryUnit(enum.Enum):
"""Units of memory."""
GB = 'GB'
TB = 'TB'
PB = 'PB'
Run Code Online (Sandbox Code Playgroud)
class Memory(BaseModel):
"""Normalized amount of memory."""
amount: int
unit: MemoryUnit
Run Code Online (Sandbox Code Playgroud)
现在我想为这个班级实现基本算术。加法、减法和乘法很容易注释:
def __add__(self, other: Memory) -> Memory: ...
def __sub__(self, other: Memory) -> Memory: ...
def __mul__(self, other: int) -> Memory: ...
Run Code Online (Sandbox Code Playgroud)
不过,我对分裂有疑问。我看到除法的两个用例:
Memory并Memory得到 a float(两个存储量之间的比率是多少)。Memory并int得到(如果均匀除以Memory的数量是多少)Memorynmypy 有没有办法用这个特定的签名来注释函数?
我有许多导入其他非类型化库的文件。
我已将此添加到mypy.ini例如:
[coloredlogs]
ignore_missing_imports = True
Run Code Online (Sandbox Code Playgroud)
那么也许这可以不检查库本身?例如,在 a/venv但仍在 every.single.place 中导入了一个库,我收到这些警告。
我可以让忽略工作的唯一方法是在 every.single.import 上添加注释
import coloredlogs # type: ignore
参考文献:https://mypy.readthedocs.io/en/stable/running_mypy.html#missing-imports
我怀疑答案是肯定的,但我想问清楚。例如,如果我有一个函数需要使用一个numpy对象,但我没有numpy直接在我的模块中使用,我可以使用前向引用来键入提示我的参数而不是numpy直接导入吗?
换句话说(假设Python 3.7+),我可以这样做吗
# forward-reference.py
def my_func(arr: "np.ndarray") -> int:
# does some operations with arr
Run Code Online (Sandbox Code Playgroud)
而不是这个
# direct-import.py
import numpy as np
def my_func(arr: np.ndarray) -> int:
# do some operations on arr...
Run Code Online (Sandbox Code Playgroud)
我无法想象核心开发人员会要求程序员仅仅为了类型提示而导入模块。我pylint的或flake8linter 会正确地将它们拾取为未使用的模块,我认为所有这些额外的导入将是相当多余的。
为了测试,我创建了两个文件:demo1.py和demo2.py(都位于同一目录中):
# demo1.py
import numpy as np
from demo2 import my_func
if __name__ == "__main__":
a = np.array([1, 2, 3])
print(my_func(a))
Run Code Online (Sandbox Code Playgroud)
# demo2.py
def my_func(arr: "np.ndarray") -> …Run Code Online (Sandbox Code Playgroud) 我创建了一个完全类型化的不和谐异步库。我有一个从 aiohttp get 请求创建对象的方法,如下例所示:
async def get_bans(self):
"""|coro|
Fetches all the bans in the guild.
"""
data = await self._http.get(f"guilds/{self.id}/bans")
for ban_data in data:
yield Ban.from_dict(construct_client_dict(self._client, ban_data))
Run Code Online (Sandbox Code Playgroud)
我想知道这个代码片段的返回类型以及它是否应该是 aAsyncGenerator[Ban, None]或AsyncIterator[Ban, None]。老实说,我一直在寻找一些信息,我可以找到任何能让我对这个主题有清晰想法的信息。
我想知道是否有办法在 Python 项目中强制执行类型提示?
目前,我正在使用mypy 预提交挂钩.pre-commit-config.yaml:
- repo: https://github.com/pre-commit/mirrors-mypy
rev: v0.931
hooks:
- id: mypy
Run Code Online (Sandbox Code Playgroud)
使用这个钩子,由于调用函数时的类型错误,我将(正确地)无法提交以下代码add:
def add(a: int, b: int) -> int:
return a + b
add(a=1.0, b=2.0)
Run Code Online (Sandbox Code Playgroud)
但是,使用上面的mypy和预提交钩子组合,类型提示仍然没有完全强制执行,我将能够在不使用类型提示的情况下提交以下代码:
def add(a, b):
return a + b
Run Code Online (Sandbox Code Playgroud)
我也很好奇,在动态类型语言(例如 Python)中强制执行类型提示是否是一个好主意?我知道我可以为我的项目选择一些静态类型语言(例如 Java),但是,我想使用带有强制类型提示的 Python 的原因是因为这允许我依赖现有的 Python 库(例如 Tensorflow),同时确保由于函数签名中指定了类型,所以编写的代码质量更好。
我喜欢在项目中创建自己的注释或输入扩展。基本上我喜欢做的是在我的项目中重用类型注释。
因此,我不想输入List[Dict[str, pd.DataFrame]]数百次,而是想将其保存到 python 变量中并以这种方式重用它。自定义注释的种类。
我们怎样才能做到这一点?
我尝试过NewType = List[Dict[str, pd.DataFrame]],但没用。从某种意义上说,自动完成功能不会暗示对象的不同功能/属性。
我想定义一个UserDict从 JSON 读取值并存储给定键的位置的函数。JSON 文件如下所示:
{
"pages": [
{
"areas": [
{
"name": "My_Name",
"x": 179.95495495495493,
"y": 117.92792792792793,
"height": 15.315315315315303,
"width": 125.58558558558553
},
...
]
}
]
}
Run Code Online (Sandbox Code Playgroud)
我想向类型 linter(例如 MyPy)表明该字典作为键是字符串,值是Position.
我当前的代码如下:
import json
from collections import UserDict
from dataclasses import dataclass, field
from pathlib import Path
from typing import Dict, List, Optional, Union
from typing_extensions import Literal
JsonPosition = Dict[str, Union[str, float]]
JsonPage = Optional[Dict[Literal["areas"], List[JsonPosition]]]
@dataclass
class Position:
"""Information for a position"""
name: str
x: …Run Code Online (Sandbox Code Playgroud) python ×10
python-typing ×10
mypy ×6
type-hinting ×4
python-3.x ×3
asynchronous ×1
generator ×1
iterator ×1
pycharm ×1
slots ×1
tuples ×1