比如说,我有一个函数,它应该做一些内部的事情,并显示提供的文本:

def display_text(text: str):
  ...
  print(text)

还有一个类,它有一个convert()方法:

class String:
  def __init__(self, string: str):
    self.string = string
  
  def convert(self):
    return self.string

现在,你可以在display_text中输入hint text参数与String,但如果提供的参数将是str,调用convert并将返回值赋给text吗?就像这样:

def display_text(text: String):
  ...
  print(text)

它应该在display_text函数中不需要任何额外的代码,只需要类型提示.我在一些libs中看到过,但不知道它是如何工作的.

我试着搜索一些库的代码(例如discord.py转换器),在StackOverflow上搜索类似的问题,只能找到大约typing.Protocol个,但仍然不知道这个转换是如何完成的.

推荐答案

你可以在display_text中输入hint text参数与String,但如果提供的参数将是str,调用convert并将返回值赋给文本,而不需要在display_text函数中添加任何额外的代码,只需要输入hinting.

不,不是类型提示的just,因为类型注释在运行时是绝对惰性的,什么都不做(from __future__ import annotations,它们甚至不被判断).如果这是一个技巧性的问题,并且"in a display_text函数"是关键,那么是的,你可以@修饰你的函数(或者修饰一个包含它们的类,或者使用元类)来包装函数,如果需要的话,使用类型注释来强制转换参数.

一个这样的decorator 的例子:

import dataclasses
import inspect
from functools import wraps
from typing import Any


def convert_args(fn):
    @wraps(fn)
    def wrapper(*args, **kwargs):
        sig = inspect.signature(fn)
        bound_args = sig.bind(*args, **kwargs)
        bound_args.apply_defaults()
        for name, val in bound_args.arguments.items():
            param = sig.parameters[name]
            if hasattr(param.annotation, "convert"):
                bound_args.arguments[name] = param.annotation.convert(val)
        return fn(*bound_args.args, **bound_args.kwargs)

    return wrapper


@dataclasses.dataclass
class Shouty:
    val: str

    @classmethod
    def convert(cls, val: Any):
        return Shouty(val=str(val).upper())


@dataclasses.dataclass
class Shorten:
    val: str

    @classmethod
    def convert(cls, val: Any):
        return Shorten(val=str(val)[::2])


@convert_args
def display_text(arg1: Shouty, arg2: Shorten):
    print(locals())


display_text("hello", "world, this is an example")

这是打印出来的

{'arg1': Shouty(val='HELLO'), 'arg2': Shorten(val='wrd hsi neape')}

Python相关问答推荐

Python 3.12中的通用[T]类方法隐式类型检索

我在使用fill_between()将最大和最小带应用到我的图表中时遇到问题

Pandas 有条件轮班操作

处理带有间隙(空)的duckDB上的重复副本并有效填充它们

管道冻结和管道卸载

在Python中管理打开对话框

如何在Python中获取`Genericums`超级类型?

如何合并两个列表,并获得每个索引值最高的列表名称?

如何在达到end_time时自动将状态字段从1更改为0

重置PD帧中的值

如何检测鼠标/键盘的空闲时间,而不是其他输入设备?

有没有办法在不先将文件写入内存的情况下做到这一点?

ModuleNotFoundError:Python中没有名为google的模块''

Django在一个不是ForeignKey的字段上加入'

我怎么才能用拉夫分拣呢?

修改.pdb文件中的值并另存为新的

以极轴表示的行数表达式?

关于数字S种子序列内部工作原理的困惑

如何批量训练样本大小为奇数的神经网络?

如何将参数名作为参数传入到函数中?