我正在使用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)
我应该写什么而不是“???”?
我需要我的模型接受字节类型变量或字符串类型变量,并在传递任何其他类型时引发异常。
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)
可以一次性拿到吗?
我正在尝试自动将 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 Listtyping.get_origin(type(TestModel).__fields__['tags'].type_) == List令人沮丧的是,这确实返回True:
type(TestModel).__fields__['tags'].type_ is str我确认字段是List类型的正确方法是什么?
我正在阅读一篇关于 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 会成为更好的打字选择。使用其中一种比另一种有好处吗?
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.
请检查下面的代码
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) 您可以\xe2\x80\x99t 使用类型类型,例如Dict[str, int]在检查中isinstance:
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])\nRun Code Online (Sandbox Code Playgroud)\n\n然而,任何进行类型检查的库都需要能够执行类似的操作isinstance(myvar, Dict[str, int])(...我意识到它应该被称为与 不同的东西isinstance,这不是完全相同的事情)
我觉得适用于打字的等效函数必须存在于某个地方,也许在mypy项目中?(但是里面\xe2\x80\x99s有很多复杂的代码,到目前为止我找不到\xe2\x80\x99)
\n\n除了 mypy 之外,还有很多项目需要这个,例如像pydantic和 AFAICT 这样的库,它们都有复杂的手动实现,并且似乎有很多边缘情况(或者只是 …
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)
正如所料,具体子类Concrete1和Concrete2继承method从他们各自的超类。此行为记录在PEP的显式声明实现部分:
要明确声明某个类实现了给定的协议,可以将其用作常规基类。在这种情况下,类可以使用协议成员的默认实现。
...
请注意,显式和隐式子类型之间几乎没有区别,显式子类化的主要好处是“免费”获得一些协议方法。
然而,当协议类实现__init__的方法,__init__是 …
我想使用一个类型检查器来帮助我编写好的代码,而且我认为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”)
有没有一种方法可以像我一样编写它,但是类型检查器可以理解它?
我想根据预定义的类型定义一个函数签名(参数和返回类型)。
假设我有这种类型:
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)