bba*_*ker 5 python python-3.x mypy
是否可以在 Python 3.6+ 中实现自定义的自动/隐式转换(又名强制转换),而不会让mypy其他静态分析器感到难过?一个例子是 a def(foo: A),并给出def b_to_a(b: B) -> A,有没有办法我可以写foo(some_b)(where some_b: B) 而不是foo(b_to_a(some_b))?
我认为在 Python 的动态中肯定有一些很好的方法可以做到这一点(例如,将成员添加到包含转换器的类),甚至将此类转换器添加到函数对象本身,以便它可以处理选定类型的转换,但我目前对 Python 类型的理解让我觉得它不会满足mypy等等。
要进行比较,请参阅 Scala 的隐式转换。
这是我想出的此功能的实现。我们为我们知道“隐式”转换的类型保留了一个单调度转换器的字典。我们使用@implicit装饰器为此添加转换器。
然后我们有一个@coerce装饰器,可以在运行时检查函数注释,获取适当的转换器并应用转换。下面是框架:
from functools import wraps, singledispatch
from inspect import signature
from collections import OrderedDict
converters = {}
def implicit(func):
ret = func.__annotations__.get('return', None)
if not ret or len(func.__annotations__) != 2:
raise ValueError("Function not annotated properly or too many params")
if ret not in converters:
@singledispatch
def default(arg):
raise ValueError("No such converter {} -> {}".format(type(arg).__name__, ret.__name__))
converters[ret] = default
else:
default = converters[ret]
t = next(v for k, v in func.__annotations__.items() if k != 'return')
default.register(t)(func)
return wraps(func)(default)
def convert(val, t):
if isinstance(val, t):
return t
else:
return converters[t](val)
def coerce(func):
@wraps(func)
def wrapper(*args, **kwargs):
sig = signature(func)
bound = sig.bind(*args, **kwargs)
bound.apply_defaults()
bound.arguments = OrderedDict(
(param, convert(val, sig.parameters[param].annotation))
for param, val in bound.arguments.items())
return func(*bound.args, **bound.kwargs)
return wrapper
Run Code Online (Sandbox Code Playgroud)
和一个例子:
from typing import Tuple, Type
@implicit
def str_to_int(a: str) -> int:
return int(a)
@implicit
def float_to_int(a: float) -> int:
return int(a)
@coerce
def make_ints(a: int, b: int) -> Tuple[Type, Type]:
return (type(a), type(b))
print(make_ints("20", 5.0))
# (<class 'int'>, <class 'int'>)
Run Code Online (Sandbox Code Playgroud)
我不认为这是一个转换问题。但看起来像是注释问题。
第一,如果foo只能处理A,怎么可能接受B?如果也foo可以处理B,为什么它应该只接受A?
其次,如果你想注释fooaccept Aor B,你可以使用def(foo: Union[A, B]).
最后,如果您的意思B是应该有一些方法使其可以由只能处理A. 它仍然是 的一个实例B。如果没有正确的注释,您的静态分析器仍然会警告您。
| 归档时间: |
|
| 查看次数: |
1086 次 |
| 最近记录: |