I have a function which validates its argument to accept only values from a given list of valid options. Typing-wise, I reflect this behavior using a Literal type alias, like so:
from typing import Literal
VALID_ARGUMENTS = ['foo', 'bar']
Argument = Literal['foo', 'bar']
def func(argument: 'Argument') -> None:
if argument not in VALID_ARGUMENTS:
raise ValueError(
f'argument must be one of {VALID_ARGUMENTS}'
)
# ...
Run Code Online (Sandbox Code Playgroud)
这违反了 DRY 原则,因为我必须在我的 Literal 类型的定义中重写有效参数列表,即使它已经存储在变量 中VALID_ARGUMENTS。给定变量,如何Argument动态创建Literal 类型VALID_ARGUMENTS …
我试图在函数签名中重用数据类中的类型提示 - 也就是说,无需再次输入签名。
解决这个问题的最佳方法是什么?
from dataclasses import dataclass
from typing import Set, Tuple, Type
@dataclass
class MyDataClass:
force: Set[Tuple[str, float, bool]]
# I've had to write the same type annotation in the dataclass and the
# function signature - yuck
def do_something(force: Set[Tuple[str, float, bool]]):
print(force)
# I want to do something like this, where I reference the type annotation from
# the dataclass. But, doing it this way, pycharm thinks `force` is type `Any`
def do_something_2(force: Type["MyDataClass.force"]):
print(force)
Run Code Online (Sandbox Code Playgroud) 我有一个如下的基类:
class BaseClass:
@classmethod
def create(cls, arg1: str) -> BaseClass:
instance = cls(arg1)
return instance
Run Code Online (Sandbox Code Playgroud)
还有一个像这样的派生类:
class DerivedClass(BaseClass):
def __init__(self, arg: str) -> None:
self.arg = arg
Run Code Online (Sandbox Code Playgroud)
现在当我这样做时
data: DerivedClass = DerivedClass.create('first arg)
Run Code Online (Sandbox Code Playgroud)
mypy 给出以下错误:
"BaseClass" cannot be assigned to declared type "DerivedClass"
"BaseClass" is incompatible with "DerivedClass"
Run Code Online (Sandbox Code Playgroud)
我如何解决它是通过使用typing.cast
data: DerivedClass = cast(
DerivedClass,
DerivedClass.get(derived_class_instance)
)
Run Code Online (Sandbox Code Playgroud)
我应该如何解决它而不使用typing.cast
例如我们有一个类:
class A:
def send(msg: bytes) -> None:
# implementation...
pass
def recv(n: int) -> bytes:
# implementation
pass
Run Code Online (Sandbox Code Playgroud)
和一个函数:
def a(obj, n: int) -> None:
received = obj.recv(n)
obj.send(received)
Run Code Online (Sandbox Code Playgroud)
很明显,不仅类的实例A可以作为参数传递obj,而且 的实例socket.socket,也许是其他已经实现的类的recv实例也可以作为send参数传递。
如何注释/键入提示obj参数,使其显示如下内容:
obj type must possess methods send and recv
send method must be of type Callable[[bytes], None]
recv method must be of type Callable[[int], bytes]
Run Code Online (Sandbox Code Playgroud) 我定义一个类如下:
from numbers import Number
from typing import Dict
from typeguard import typechecked
Data = Dict[str, Number]
@typechecked
class Foo:
def __init__(self, data: Data):
self._data = dict(data)
@property
def data(self) -> Data:
return self._data
Run Code Online (Sandbox Code Playgroud)
我在用typeguard。我的目的是限制可以进入数据字典的类型。显然,typeguard如果将整个字典传递给函数或从函数返回,则会检查整个字典。如果字典直接“暴露”,那么检查类型就成为字典的“责任”——这显然是行不通的:
bar = Foo({'x': 2, 'y': 3}) # ok
bar = Foo({'x': 2, 'y': 3, 'z': 'not allowed'}) # error as expected
bar.data['z'] = 'should also be not allowed but still is ...' # no error, but should cause one
Run Code Online (Sandbox Code Playgroud)
我在 typeshed 中看到过这样的行:
但os.PathLike似乎并不通用。它不允许传递字符串。
import os
import pathlib
def test(f: os.PathLike[str]):
print(pathlib.Path(f))
test(r"C:\Program Files")
Run Code Online (Sandbox Code Playgroud)
上面的代码片段失败了 Mypy。
我目前正在努力向项目添加类型提示,但不知道如何做到这一点。我有一个列表列表,其中嵌套列表包含两个 int 和 float 类型的元素。嵌套列表的第一个元素始终是 int,第二个元素始终是 float。
my_list = [[1000, 5.5], [1432, 2.2], [1234, 0.3]]
Run Code Online (Sandbox Code Playgroud)
我想对它进行类型注释,以便在 for 循环或循环理解中解包内部列表以保留类型信息。我可以将内部列表更改为元组,并得到我正在寻找的内容:
def some_function(list_arg: list[tuple[int, float]]): pass
Run Code Online (Sandbox Code Playgroud)
但是,我需要内部列表是可变的。有没有一种好的方法可以对列表执行此操作?我知道像 Sequence 和 Collection 这样的抽象类不支持多种类型。
假设我有一个完全类型提示的方法,仅包含关键字参数:
class A:
def func(a: int, b: str, c: SomeIntricateTypeHint) -> OutputClass:
...
Run Code Online (Sandbox Code Playgroud)
现在假设我有一个函数,它接受可变关键字参数,并将它们完全传递给该方法:
def outer_func(n_repeat: int, **kwargs: ???) -> OtherOutputClass:
a = A()
for _ in range(n_repeat):
a.func(**kwargs)
Run Code Online (Sandbox Code Playgroud)
这样做,我失去了 类型提示的好处func。我如何输入提示kwargs才能outer_func恢复这些好处?
对于额外的细节,就我而言,我个人不定义func. 它实际上是来自客户端对象的方法boto3。因此,我正在寻找一种动态创建类型提示的解决方案,而不必手动创建 TypedDict。
我了解内置类型。但是我如何指定稀有对象,例如数据库连接对象?
def get_connection_and_cursor() -> tuple[psycopg2.extensions.cursor, psycopg2.extensions.connection]:
connection = psycopg2.connect(dbname=db_name, user=db_user, password=db_password, host='127.0.0.1', port="5432")
# connection.autocommit = True
cursor = connection.cursor()
return connection, cursor
Run Code Online (Sandbox Code Playgroud)
检查类型,以下是输出:
type(cursor):psycopg2.extensions.cursor和type(connection)psycopg2.extensions.connection: 。我应该用它做什么?
源代码example.py:
from typing import Union, Any
import numpy as np
Number = Union[int, float, np.floating[Any]]
def add_one(num: Number) -> Number:
return num + 1
inputs = [1, 2, 3]
outputs = [add_one(n) for n in inputs]
avg = np.mean(outputs)
Run Code Online (Sandbox Code Playgroud)
运行 mypy:
mypy example.py
src/example.py:14: error: Argument 1 to "mean" has incompatible type "List[Union[float, floating[Any]]]"; expected "Union[_SupportsArray[dtype[Any]], _NestedSequence[_SupportsArray[dtype[Any]]], bool, int, float, complex, str, bytes, _NestedSequence[Union[bool, int, float, complex, str, bytes]]]"
Found 1 error in 1 file (checked 1 source …Run Code Online (Sandbox Code Playgroud) python ×10
python-typing ×10
mypy ×4
type-hinting ×4
annotations ×2
types ×2
alias ×1
dictionary ×1
numpy ×1
python-3.9 ×1
python-3.x ×1