标签: python-typing

Python typing: Dynamically Create Literal Alias from List of Valid Values

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 …

python python-typing

8
推荐指数
2
解决办法
1474
查看次数

重用数据类类型提示

我试图在函数签名中重用数据类中的类型提示 - 也就是说,无需再次输入签名。

解决这个问题的最佳方法是什么?

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)

python alias python-3.x mypy python-typing

8
推荐指数
1
解决办法
2955
查看次数

Python类型:注释父类返回子类类型对象的最佳方式

我有一个如下的基类:

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

python mypy python-typing

8
推荐指数
1
解决办法
2022
查看次数

Python:“有方法”的类型提示

例如我们有一个类:

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)

python types annotations type-hinting python-typing

8
推荐指数
1
解决办法
1162
查看次数

如何对字典(在运行时)进行类型提示/类型检查以查找任意数量的任意键/值对?

我定义一个类如下:

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)

PEP 589 …

python dictionary type-hinting python-typing

8
推荐指数
1
解决办法
2877
查看次数

os.PathLike[Any] 与 os.PathLike[str]

我在 typeshed 中看到过这样的行:

https://github.com/python/typeshed/blob/994b69ef8f18e76689daca3947879c3d7f76173e/stdlib/_typeshed/__init__.pyi#L77

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

python type-hinting mypy python-typing python-3.9

8
推荐指数
1
解决办法
5567
查看次数

用于具有多种类型的通用可变元组/固定长度序列的 Python 类型提示

我目前正在努力向项目添加类型提示,但不知道如何做到这一点。我有一个列表列表,其中嵌套列表包含两个 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 这样的抽象类不支持多种类型。

python type-hinting data-structures python-typing

8
推荐指数
1
解决办法
1136
查看次数

当它们按原样传递给另一个函数时,如何输入提示 kwargs?

假设我有一个完全类型提示的方法,仅包含关键字参数:

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。

python python-typing

8
推荐指数
1
解决办法
1785
查看次数

稀有对象的 python 类型注释,例如 psycopg2 对象

我了解内置类型。但是我如何指定稀有对象,例如数据库连接对象?

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: 。

我应该用它做什么?

python types annotations python-typing

7
推荐指数
1
解决办法
5904
查看次数

如何输入hint函数以与numpy兼容

源代码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 numpy mypy python-typing

7
推荐指数
1
解决办法
2044
查看次数