标签: python-typing

解包对象属性时是否可以维护类型信息?

想象一下我有一个对象,它是一个类的实例,如下所示:

@dataclass
class Foo:
    bar: int
    baz: str
Run Code Online (Sandbox Code Playgroud)

我使用它是dataclasses为了方便,但在这个问题的上下文中,不要求该类是dataclass.

通常,如果我想解压此类对象的属性,我必须实现__iter__,例如如下:

class Foo:
    ...
    def __iter__(self) -> Iterator[Any]:
        return iter(dataclasses.astuple(self))

bar, baz = Foo(1, "qux")
Run Code Online (Sandbox Code Playgroud)

然而,从像Pyright这样的静态类型检查器的角度来看,我现在丢失了bar和的任何类型信息baz,它只能推断出它们的类型Any。我可以通过iter手动创建元组参数来稍微改进:

    def __iter__(self) -> Iterator[Union[str, int]]:
        return iter((self.bar, self.baz))
Run Code Online (Sandbox Code Playgroud)

但我仍然没有bar和的特定类型baz。我可以注释bar然后直接baz使用,dataclasses.astuple如下:

bar: str
baz: int
bar, baz = dataclasses.astuple(Foo(1, "qux"))
Run Code Online (Sandbox Code Playgroud)

但这需要可读性较差的多级列表理解,例如

bars: list[int] = [
    bar for bar, _ in [dataclasses.astuple(foo) for …
Run Code Online (Sandbox Code Playgroud)

python iterable-unpacking python-typing pyright

5
推荐指数
1
解决办法
401
查看次数

我可以使用 Typing_extensions 中的实验类型吗?

更具体:

要解决诸如如何使用封闭类的类型键入提示方法之类的问题?
PEP 673介绍typing.Self。PEP 是一个草案,但目前它是 Typing_extensions 4.0.0 中的实验类型

我尝试在 python 3.8 中使用它

@dataclasses.dataclass
class MenuItem:
    url: str
    title: str
    description: str = ""
    items: typing.List[typing_extensions.Self] = dataclasses.field(default_factory=list)
Run Code Online (Sandbox Code Playgroud)

但它提高了

TypeError: Plain typing_extensions.Self is not valid as type argument
Run Code Online (Sandbox Code Playgroud)

我可以只使用文字字符串“MenuItem”来代替。但我想知道为什么这不起作用。

python python-typing

5
推荐指数
1
解决办法
3747
查看次数

如何使用 TypeVar 键入 __iter__ ?

我正在尝试创建一个具有通用类型的数据类,我可以将其解压并作为 numpy 的 linspace 的参数提供。__iter__为此,我需要使用 TypeVar给出返回类型:

from typing import Iterator, Union, Generic, TypeVar, Any
import numpy as np

VT = TypeVar("VT", bound=float)

class Arguments(Generic[VT]):
    def __init__(self, start: VT, stop: VT, num: int):
        self.start = start
        self.stop = stop
        self.num = num

    def __iter__(self) -> Iterator[Union[VT, int]]:
        return iter([self.start, self.stop, self.num])

args: Arguments[float] = Arguments(1.2, 2.5, 10)

print(np.linspace(*args))
Run Code Online (Sandbox Code Playgroud)

执行工作正常,但 mypy (0.920) 失败并出现以下错误:

$ mypy test.py
test.py:17: error: No overload variant of "linspace" matches argument type "Arguments[float]"  [call-overload]
test.py:17: note: …
Run Code Online (Sandbox Code Playgroud)

python mypy python-typing

5
推荐指数
1
解决办法
656
查看次数

Python 中的多态性和类型提示

考虑以下情况:

class Base:
    ...

class Sub(Base):
    ...

def get_base_instance(*args) -> Base:
    ...

def do_something_with_sub(instance: Sub):
    ...
Run Code Online (Sandbox Code Playgroud)

假设我get_base_instance在一个上下文中调用,我知道它会返回一个Sub实例 - 也许基于args我传递的内容。现在我想将返回的实例传递给do_something_with_sub

sub_instance = get_base_instance(*args)
do_something_with_sub(sub_instance)
Run Code Online (Sandbox Code Playgroud)

问题是我的 IDE 抱怨将Base实例传递给仅接受实例的方法Sub

我想我记得在其他编程语言中,我只是将返回的实例转换为Sub. 我该如何解决Python中的问题?根据返回类型有条件地抛出异常,或者有更好的方法吗?

python polymorphism python-typing

5
推荐指数
1
解决办法
961
查看次数

协议的所有基础都必须是协议——typing.MutableMapping 不是协议吗?

我想为自定义映射类定义一个类型协议。这个类需要与 a 非常相似,除了它除了那些定义为抽象方法(特别是)MutableMapping之外还有几个附加方法,并且我还想提前指定自定义映射类的任何实现必须使用哪些类型作为键和值。collections.abc.MutableMapping.copy()

读完PEP 544后,我想我应该能够做到这一点:

from typing import Hashable, MutableMapping, Protocol, TypeVar


TVarMapProt = TypeVar("TVarMapProt", bound="VariableMappingProtocol")


class VariableMappingProtocol(MutableMapping[Hashable, int], Protocol):
    """
    Protocol for the type behaviour of a class which
    acts basically like a dict of int objects.
    """

    def copy(self: TVarMapProt) -> TVarMapProt:
         # TODO replace return type with Self if PEP 673 goes through
        ...
Run Code Online (Sandbox Code Playgroud)

我的想法是,在我的代码中,我可以声明需要一个类型VariableMappingProtocol,然后用户必须使用自己定义的类,以避免输入错误:

TCusVarMap = TypeVar("CusVarMap", bound="CustomVariableMapping")


class CustomVariableMapping
    """Defines all the methods that a MutableMapping does, …
Run Code Online (Sandbox Code Playgroud)

python abc structural-typing mypy python-typing

5
推荐指数
0
解决办法
568
查看次数

有没有办法用 mypy 覆盖 python 中继承的类属性类型?

我编写了一个defaultdict可以default_factory使用 key 作为参数进行调用的子类。

from collections import defaultdict
from typing import TypeVar, Any, Callable, Generic

K = TypeVar('K')


class keydefaultdict(defaultdict, Generic[K]):
    ''' Drop-in replacement for defaultdict accepting key as argument '''

    default_factory: Callable[[], Any] | Callable[[K], Any] | None

    def __missing__(self, key: K) -> Any:
        if self.default_factory is None:
            raise KeyError(key)
        else:
            try:
                ret = self[key] = self.default_factory(key)
            except TypeError:  # try no-key signature
                ret = self[key] = self.default_factory()
            # if failed, let the error propagate as …
Run Code Online (Sandbox Code Playgroud)

python mypy python-typing python-3.10

5
推荐指数
1
解决办法
5237
查看次数

如何从Python中的多个值列表创建typing.Literal

我有两个清单。我想创建一个Literal使用这两个列表

category1 = ["image/jpeg", "image/png"]
category2 = ["application/pdf"]

SUPPORTED_TYPES = typing.Literal[category1 + category2]
Run Code Online (Sandbox Code Playgroud)

有什么办法可以做到这一点吗?

我已经看到问题了输入:Dynamically Create Literal Alias from List of Valid Values但这对我的用例不起作用,因为我不想mimetype成为类型typing.Tuple

我将使用Literal在函数中使用 -

def process_file(filename: str, mimetype: SUPPORTED_TYPES)
Run Code Online (Sandbox Code Playgroud)

我尝试过的 -

supported_types_list = category1 + category2
SUPPORTED_TYPES = Literal[supported_types_list]
SUPPORTED_TYPES = Literal[*supported_types_list]

# this gives 2 different literals, rather i want only 1 literal
SUPPORTED_TYPES = Union[Literal["image/jpeg", "image/png"], Literal["application/pdf"]]    
Run Code Online (Sandbox Code Playgroud)

python type-hinting python-typing

5
推荐指数
1
解决办法
4204
查看次数

将函数参数注释为特定模块

我有一个导入特定模块的 pytest 夹具。这是必需的,因为导入模块非常昂贵,因此我们不想在导入时(即在 pytest 测试收集期间)执行此操作。这会产生如下代码:

@pytest.fixture
def my_module_fix():
    import my_module
    yield my_module

def test_something(my_module_fix):
    assert my_module_fix.my_func() = 5
Run Code Online (Sandbox Code Playgroud)

我正在使用 PyCharm,并希望在我的测试中进行类型检查和自动完成。为了实现这一点,我必须以某种方式将my_module_fix参数注释为具有模块的类型my_module

我不知道如何实现这一目标。我发现我可以注释my_module_fix为 type types.ModuleType,但这还不够:它不是任何模块,它始终是my_module

python pytest python-typing

5
推荐指数
1
解决办法
934
查看次数

在旧版本的 Python 上使用现代输入功能

因此,我正在使用 Python 编写一个事件发射器类。

目前代码如下所示:

from typing import Callable, Generic, ParamSpec

P = ParamSpec('P')

class Event(Generic[P]):
  def __init__(self):
    ...

  def addHandler(self, action : Callable[P, None]):
    ...

  def removeHandler(self, action : Callable[P, None]): 
    ...

  def fire(self, *args : P.args, **kwargs : P.kwargs):
    ...
Run Code Online (Sandbox Code Playgroud)

如您所见,注释依赖于,它仅在 python 3.10 中ParamSpec添加。typing

虽然它在 Python 3.10(在我的机器上)中运行良好,但在 Python 3.9 及更早版本(在其他机器上)中却失败了,因为这ParamSpec是一项新功能。

那么,如何ParamSpec在运行程序时避免导入或使用一些后备替代方案,同时不混淆编辑器中的输入(pyright)?

python python-typing pyright

5
推荐指数
1
解决办法
1518
查看次数

用于 multiprocessing.Value 的 python 类型

multiprocessing.Value("d")返回一个类型multiprocessing.sharedctypes.Synchronized

所以目前我输入如下提示:
int_val: Synchronized = multiprocessing.Value("i")

有类似的东西Synchronized[int]吗?(类似于列表和其他容器类型)

python python-multiprocessing python-typing

5
推荐指数
0
解决办法
801
查看次数