我正在尝试编写一个函数来断言用户输入与定义的文字类型匹配。
基本上,给出:
MyLiteral = Literal["foo", "bar"]
Run Code Online (Sandbox Code Playgroud)
我想编写一个函数来执行此操作:
some_user_provided_value = input() # For example
good_value = assert_literal(MyLiteral, some_user_provided_value)
Run Code Online (Sandbox Code Playgroud)
现在应该将的类型good_value推断为MyLiteral。如果用户值与任何定义的文字字符串都不匹配,则会引发断言错误。
这应该具有与以下相同的效果:
some_user_provided_value = input() # For example
good_value: MyLiteral
if some_user_provided_value == "foo":
good_value = "foo"
elif some_user_provided_value == "bar":
good_value = "bar"
else:
raise AssertionError(f"Value {some_user_provided_value!r} is not a MyLiteral")
Run Code Online (Sandbox Code Playgroud)
这是我的项目中经常重复的模式,因此我想将其包装在一个函数中。
该函数看起来像这样:
from typing import Any, TypeVar
T = TypeVar("T")
def assert_literal(literal_type: T, value: Any) -> T:
if value not in typing.get_args(literal_type):
raise AssertionError(f"Value {value!r} is not …Run Code Online (Sandbox Code Playgroud) 我有一个数据类,比方说:
from dataclasses import dataclass
@dataclass
class Foo:
bar: int
baz: int
Run Code Online (Sandbox Code Playgroud)
我有一个从接收 json 并将其作为字典加载的 API 调用的函数:
def handler(foo) -> Foo:
return Foo(**foo)
Run Code Online (Sandbox Code Playgroud)
有没有一种方法可以输入 foo 而无需实际创建TypedDict数据类的镜像?
例如:
from typing_extensions import TypedDict
class SerializedFoo(TypedDict):
bar: int
baz: int
Run Code Online (Sandbox Code Playgroud)
我觉得必须定义两者很奇怪。
我总是认为 Callable 相当于拥有 dunder__call__但显然也有__name__,因为以下代码是正确的mypy --strict:
def print_name(f: Callable[..., Any]) -> None:
print(f.__name__)
def foo() -> None:
pass
print_name(foo)
print_name(lambda x: x)
Run Code Online (Sandbox Code Playgroud)
python Callable 的实际接口是什么?
我挖出了什么functools.wraps。AFAIU 设定('__module__', '__name__', '__qualname__', '__doc__', '__annotations__')- 这与Callable预期的相同吗?
我有 3 个简单的类,例如:
class Animal(abc.ABC):
...
class Cat(Animal):
...
class Dog(Animal):
...
Run Code Online (Sandbox Code Playgroud)
然后我有一个注释如下的函数:
def speak(animals: List[Animal]) -> List[str]:
...
Run Code Online (Sandbox Code Playgroud)
我的问题是我想限制List[Animal]只包含一种动物,所以:
speak([Dog(), Dog()]) # OK
speak([Cat(), Cat()]) # OK
speak([Cat(), Dog()]) # typing error
Run Code Online (Sandbox Code Playgroud)
我将如何注释该speak函数以实现此目的?是否可以使用打字来完成,或者我是否被迫在运行时检查这一点?
我尝试使用上面的方法,但是在调用likeList[Animal]时不会出现错误。speakspeak([Cat(), Dog()])
我也尝试过使用泛型,TypeVar('T', bound=Animal)但这仍然允许我传递子List类的任意组合。
假设我有一个带有许多参数的函数,例如
import pandas as pd
def f(df: pd.DataFrame, a: int, b: int, c: int, d: int, inplace: bool = True) -> Optional[pd.DataFrame]:
raise NotImplementedError
Run Code Online (Sandbox Code Playgroud)
该函数将修改数据帧 ifinplace=True并返回修改后的副本 if inplace=False。
我知道我能做到
@overload
def f(df: pd.DataFrame, a: int, b: int, c: int, d: int, inplace: Literal[True] = True) -> None:
...
@overload
def f(df: pd.DataFrame, a: int, b: int, c: int, d: int, inplace: Literal[False] = True) -> pd.DataFrame:
...
Run Code Online (Sandbox Code Playgroud)
通知打字系统这一事实。
但是,我想知道是否有一种方法可以在不重复整个函数定义的情况下执行此操作,如果有很多参数,这似乎很麻烦。我正在寻找类似的东西
@overload
def f(..., inplace: Literal[True]) -> None:
... …Run Code Online (Sandbox Code Playgroud) 我试图使用重载来使可变参数函数的返回类型以某种方式依赖于其参数的类型。具体来说,当且仅当其任何参数的类型为 X 时,我希望返回类型为X。
考虑以下最小示例:
from typing import overload
class Safe:
pass
class Dangerous:
pass
@overload
def combine(*args: Safe) -> Safe: ...
@overload
def combine(*args: Safe | Dangerous) -> Safe | Dangerous: ...
def combine(*args: Safe | Dangerous) -> Safe | Dangerous:
if all(isinstance(arg, Safe) for arg in args):
return Safe()
else:
return Dangerous()
reveal_type(combine())
reveal_type(combine(Safe()))
reveal_type(combine(Dangerous()))
reveal_type(combine(Safe(), Safe()))
reveal_type(combine(Safe(), Dangerous()))
Run Code Online (Sandbox Code Playgroud)
这输出
example.py:21: note: Revealed type is "example.Safe"
example.py:22: note: Revealed type is "example.Safe"
example.py:23: note: Revealed …Run Code Online (Sandbox Code Playgroud) 如何指定typing我的函数仅接受特定的可调用对象?例如,我想要类似于这样的功能:
import typing
def accepted_function1():
pass
def accepted_function2():
pass
def function_accepting_functions(foo: Literal[accepted_function1, accepted_function2]):
foo()
Run Code Online (Sandbox Code Playgroud) 我是 Python 3 中的静态类型提示的忠实粉丝和拥护者。我已经使用它们一段时间了,没有任何问题。
我刚刚遇到了一个我似乎无法编译的新边缘案例。如果我想定义一个自定义类型,然后定义它的参数怎么办?
例如,这在 Python 3 中很常见:
from typing import List, NewType
CustomObject = NewType('CustomObject', List[int])
def f(data: List[CustomObject]):
# do something
Run Code Online (Sandbox Code Playgroud)
但这不会编译:
class MyContainer():
# some class definition ...
from typing import NewType
SpecialContainer = NewType('SpecialContainer', MyContainer)
def f(data: SpecialContainer[str]):
# do something
Run Code Online (Sandbox Code Playgroud)
我意识到SpecialContainer在这种情况下这在技术上是一个函数,但它不应该在类型签名的上下文中被评估为一个函数。第二个代码片段失败,TypeError: 'function' object is not subscriptable.
我有一个做某事的父类和两个以正交方式包装方法的子类。当我尝试组合两个子类时,mypy 抱怨以下错误。
基类“Foo”中“run”的定义与基类“Bar”中的定义不兼容
这两个类如何“不兼容”以及如何修改我的代码以安抚 mypy?我可以不做就做吗
class Parent:
def run(self, a, b):
pass
class Foo(Parent):
def run(self, a, b, foo=None, **kwargs):
print('foo', foo)
super().run(a, b, **kwargs)
class Bar(Parent):
def run(self, a, b, bar=None, **kwargs):
print('bar', bar)
super().run(a, b, **kwargs)
class C(Foo, Bar):
pass
Run Code Online (Sandbox Code Playgroud) 我已经输入了包含这些行的代码。
from typing import Dict, List, Set, Tuple
def pairs_sum_to_k(a_set: Set[int], k: int) -> List[Tuple[int, int]]:
...
Run Code Online (Sandbox Code Playgroud)
代码编译并运行。那挺好的。当我尝试导入typingColab中没有的内容时,生成了一条错误消息,这也很好。
不好的是,当类型提示与程序不一致时,例如,将返回类型更改为 simple int,Colab 没有抱怨。这表明 Colab 可以处理类型提示语法,但它对类型声明根本不做任何事情。是这样吗?我应该期待 Colab 提供什么样的打字支持(如果有)?
谢谢。
python ×10
python-typing ×10
mypy ×5
overloading ×2
python-3.x ×2
python-3.5 ×1
python-3.6 ×1
type-hinting ×1
typeddict ×1
typing ×1