标签: python-typing

Python 类型:未知深度的嵌套字典

我正在使用Python 3.11。strs 的 dicts 的 dict 的类型提示将如下所示:

dict[dict[str, str]]
Run Code Online (Sandbox Code Playgroud)

但是如果我想为未知深度的字典提供提示怎么办?

例如,我想编写一个函数,它从元组列表(父级,后代)以字典形式构造树:

source = [('a', 'b'), ('b', 'c'), ('d', 'e')]
target = {'a': {'b': {'c': {}}}, 'd': {'e': {}}}


def tree_form(source: list[tuple[str, str]]) -> ???:
    """code"""
    pass
Run Code Online (Sandbox Code Playgroud)

我应该写什么而不是“???”?

python python-typing

4
推荐指数
1
解决办法
916
查看次数

如何通过 Typing.Union 在 pydantic.BaseModel 中使用两种变量类型?

我需要我的模型接受字节类型变量或字符串类型变量,并在传递任何其他类型时引发异常。

from typing import Union

from pydantic import BaseModel


class MyModel(BaseModel):
    a: Union[bytes, str]


m1 = MyModel(a='123')
m2 = MyModel(a=b'123')

print(type(m1.a))
print(type(m2.a))
Run Code Online (Sandbox Code Playgroud)

就我而言,模型将字节和字符串解释为字节。

输出:

<class 'bytes'>
<class 'bytes'>
Run Code Online (Sandbox Code Playgroud)

期望的输出:

<class 'str'>
<class 'bytes'>
Run Code Online (Sandbox Code Playgroud)

如果我重新分配成员 a,则可以实现上述所需的输出:

<class 'bytes'>
<class 'bytes'>
Run Code Online (Sandbox Code Playgroud)

可以一次性拿到吗?

python python-typing pydantic

4
推荐指数
1
解决办法
3855
查看次数

无法确定 Pydantic 模型中的字段类型是否为列表类型

我正在尝试自动将 Pydantic 模型转换为数据库模式。为此,我递归地循环遍历 Pydantic 模型的字段以确定字段的类型。

作为一个例子,我有这个简单的模型:

from typing import List
from pydantic import BaseModel

class TestModel(BaseModel):
    tags: List[str]
Run Code Online (Sandbox Code Playgroud)

__fields__我使用此处描述的属性递归模型: https ://docs.pydantic.dev/usage/models/#model-properties

如果我这样做,type(TestModel).__fields__['tags']我会看到:

ModelField(name='tags', type=List[str], required=True)
Run Code Online (Sandbox Code Playgroud)

我想以编程方式检查该ModelField类型是否有List起源。我尝试过以下方法,但没有一个有效:

  • type(TestModel).__fields__['tags'].type_ is List[str]
  • type(TestModel).__fields__['tags'].type_ == List[str]
  • typing.get_origin(type(TestModel).__fields__['tags'].type_) is List
  • typing.get_origin(type(TestModel).__fields__['tags'].type_) == List

令人沮丧的是,这确实返回True

  • type(TestModel).__fields__['tags'].type_ is str

我确认字段是List类型的正确方法是什么?

python python-typing pydantic

4
推荐指数
1
解决办法
2945
查看次数

collections.abc.Sequence 和打字.Sequence 之间的区别

我正在阅读一篇关于 collection.abc 和 python 标准库中的类型类的文章,发现这两个类具有相同的功能。

我使用下面的代码尝试了这两个选项并得到了相同的结果

from collections.abc import Sequence

def average(sequence: Sequence):
    return sum(sequence) / len(sequence)

print(average([1, 2, 3, 4, 5]))  # result is 3.0

from typing import Sequence

def average(sequence: Sequence):
    return sum(sequence) / len(sequence)

print(average([1, 2, 3, 4, 5])) # result is 3.0


Run Code Online (Sandbox Code Playgroud)

在什么情况下,collection.abc 会成为更好的打字选择。使用其中一种比另一种有好处吗?

python generic-collections python-3.x python-typing

4
推荐指数
1
解决办法
4866
查看次数

How to type hint a return value of Exception's subclass?

I have an abstract method in my base class, and I want all the subclasses to return an iterable of their expected Exception classes:

class Foo(metaclass=ABCMeta):
    @abstractmethod
    def expected_exceptions(self):
        raise NotImplementedError()

class Bar(Foo):
    def expected_exceptions(self):
        return ValueError, IndexError

class Baz(Foo):
    def expected_exceptions(self):
        yield from self.manager._get_exceptions()
Run Code Online (Sandbox Code Playgroud)

How do I type hint this return value? At first I thought of -> Iterable[Exception], but that would mean they are instances of Exception, as opposed to subclasses.

python type-hinting python-3.x python-typing

3
推荐指数
1
解决办法
60
查看次数

对 NamedTuple 的 Python 类型支持

请检查下面的代码

import typing
import abc


class A(abc.ABC):
    @abc.abstractmethod
    def f(self) -> typing.NamedTuple[typing.Union[int, str], ...]:
        ...


class NT(typing.NamedTuple):
    a: int
    b: str


class B(A):

    def f(self) -> NT:
        return NT(1, "s")


print(B().f())
Run Code Online (Sandbox Code Playgroud)

我收到一个错误。在父类中A,我想定义方法f,以便指示任何子类都应该通过返回仅由ot字段NamedTuple组成的a 来覆盖它。intstr

但我收到一条错误消息:

TypeError: 'NamedTupleMeta' object is not subscriptable
Run Code Online (Sandbox Code Playgroud)

如下更改签名会有所帮助,但是我如何告诉打字系统子类可以返回仅包含 int 和 str 的 NamedTuples

TypeError: 'NamedTupleMeta' object is not subscriptable
Run Code Online (Sandbox Code Playgroud)

python python-3.x python-typing

3
推荐指数
1
解决办法
6211
查看次数

是否有针对类型类型的规范“isinstance”实现?

您可以\xe2\x80\x99t 使用类型类型,例如Dict[str, int]在检查中isinstance

\n\n
Python 3.7.6 (default, Dec 30 2019, 19:38:28)\nType \'copyright\', \'credits\' or \'license\' for more information\nIPython 7.12.0 -- An enhanced Interactive Python. Type \'?\' for help.\n\nIn [1]: from typing import Dict\n\nIn [2]: myvar = {"a": 1}\n\nIn [3]: isinstance(myvar, Dict[str, int])\n---------------------------------------------------------------------------\nTypeError                                 Traceback (most recent call last)\n<ipython-input-3-a8fee57141ae> in <module>\n----> 1 isinstance(myvar, Dict[str, int])\n
Run Code Online (Sandbox Code Playgroud)\n\n

然而,任何进行类型检查的库都需要能够执行类似的操作isinstance(myvar, Dict[str, int])(...我意识到它应该被称为与 不同的东西isinstance,这不是完全相同的事情)

\n\n

我觉得适用于打字的等效函数必须存在于某个地方,也许在mypy项目中?(但是里面\xe2\x80\x99s有很多复杂的代码,到目前为止我找不到\xe2\x80\x99)

\n\n

除了 mypy 之外,还有很多项目需要这个,例如像pydantic和 AFAICT 这样的库,它们都有复杂的手动实现,并且似乎有很多边缘情况(或者只是 …

python-3.x mypy python-typing pydantic

3
推荐指数
1
解决办法
1492
查看次数

在显式子类型构造期间未调用typing.Protocol 类`__init__` 方法

Python 的PEP 544引入typing.Protocol了结构子类型,也就是“静态鸭子类型”。

在此 PEP 关于合并和扩展协议的部分中,指出

一般的哲学是协议大多像常规的 ABC,但静态类型检查器会专门处理它们。

因此,人们期望从 的子类继承与期望从 的子类继承typing.Protocol的方式大致相同abc.ABC

from abc import ABC
from typing import Protocol

class AbstractBase(ABC):
    def method(self):
        print("AbstractBase.method called")

class Concrete1(AbstractBase):
    ...

c1 = Concrete1()
c1.method()  # prints "AbstractBase.method called"

class ProtocolBase(Protocol):
    def method(self):
        print("ProtocolBase.method called")

class Concrete2(ProtocolBase):
    ...

c2 = Concrete2()
c2.method()  # prints "ProtocolBase.method called"
Run Code Online (Sandbox Code Playgroud)

正如所料,具体子类Concrete1Concrete2继承method从他们各自的超类。此行为记录在PEP的显式声明实现部分:

要明确声明某个类实现了给定的协议,可以将其用作常规基类。在这种情况下,类可以使用协议成员的默认实现。

...

请注意,显式和隐式子类型之间几乎没有区别,显式子类化的主要好处是“免费”获得一些协议方法。

然而,当协议类实现__init__的方法,__init__是 …

protocols abstract-base-class python-3.x python-typing

3
推荐指数
1
解决办法
418
查看次数

Python NewType('X', Y):mypy 显示错误:得到 Y,预期为 X

我想使用一个类型检查器来帮助我编写好的代码,而且我认为mypy 可以满足我的需求。但是我不知道如何编写以下代码。

import typing as tau

Offset = tau.NewType('Offset', tau.Tuple[int, int])


def f(x: int, y: int) -> Offset:
    return x, y


important_for_me = Offset != tau.Tuple[int, int]
assert important_for_me
Run Code Online (Sandbox Code Playgroud)

对于我正在编写的框架,重要的是不仅要为类型分配标识符,而且我仍然希望类型检查器知道如何帮助我(所以不要只分配 TypeVar 并丢失信息)。

Typing.NewType 工作得很好,但 mypy 在第 7 行给了我一个错误:

不兼容的返回值类型(得到“Tuple[int, int]”,预期为“Offset”)

有没有一种方法可以像我一样编写它,但是类型检查器可以理解它?

错误

python type-hinting mypy python-typing

3
推荐指数
1
解决办法
135
查看次数

如何为具有预定义类型的函数(参数和返回类型)定义类型?

我想根据预定义的类型定义一个函数签名(参数和返回类型)。

假设我有这种类型:

safeSyntaxReadType = Callable[[tk.Tk, Notebook, str], Optional[dict]]
Run Code Online (Sandbox Code Playgroud)

这意味着safeSyntaxReadType是一个接收 3 个参数(来自上面列出的类型)的函数,它可以返回一个dict或可能不返回任何内容。

现在假设我使用一个函数,safeReadJsonFile其签名是:

def safeReadJsonFile(root = None, notebook = None, path = ''):
Run Code Online (Sandbox Code Playgroud)

我想将类型分配给签名中safeSyntaxReadType的函数safeReadJsonFile,可能类似于:

def safeReadJsonFile:safeSyntaxReadType(root = None, notebook = None, path = ''):
Run Code Online (Sandbox Code Playgroud)

但是这种语法不起作用。这种类型分配的正确语法是什么?

我可以这样做:

def safeReadJsonFile(root:tk.Tk = None, notebook:Notebook = None, path:str = '') -> Optional[dict]:
Run Code Online (Sandbox Code Playgroud)

但我想避免这种情况。

在阅读了很多(所有打字文档和一些PEP544)之后,我发现没有这样的语法可以在定义中轻松地将类型分配给整个函数(最接近的是@typing.overload,它并不是我们在这里需要的)。

但作为一种可能的解决方法,我实现了一个装饰器函数,它可以帮助轻松分配类型:

def func_type(function_type):
    def decorator(function):
        def typed_function(*args, **kwargs):
            return function(*args, **kwargs)
        typed_function: function_type  # type …
Run Code Online (Sandbox Code Playgroud)

python python-typing

3
推荐指数
1
解决办法
238
查看次数