首页 > 编程问答 >如何更正修饰的函数签名和类型提示?

如何更正修饰的函数签名和类型提示?

时间:2024-07-24 13:28:05浏览次数:9  
标签:python python-typing python-decorators

考虑以下装饰器,它将任何二元运算符扩展到多个参数:

from typing import Callable, TypeVar
from functools import reduce, wraps


T = TypeVar('T')


def extend(binop: Callable[[T, T], T]):
    """ Extend a binary operator to multiple arguments """

    @wraps(binop)
    def extended(*args: T) -> T:
        if not args:
            raise TypeError("At least one argument must be given")

        return reduce(binop, args)

    return extended

,然后可以按如下方式使用:

@extend
def fadd(x: float, y: float) -> float:
    """ Add float numbers """

    return x + y


@extend
def imul(x: int, y: int) -> int:
    """ Multiply integers """

    return x*y

,以便创建分别乘以和添加其输入参数的 imul fadd 函数。| ||函数

imul 将具有正确的文档字符串(因为 fadd 装饰器),但它们的签名和类型注释不正确。 例如: @wraps Gives

>>> help(fadd)

Also

fadd(x: float, y: float) -> float                                               
    Add float numbers  

这是不正确的。

>>> fadd.__annotations__                                              
{'x': <class 'float'>, 'y': <class 'float'>, 'return': <class 'float'>} 

实现装饰器以产生正确的函数签名的正确方法是什么?

我以某种方式认为如果我删除|| |line 类型提示和签名将是正确的。 但即便如此,情况也并非如此。 没有

给出 @wraps (即泛型类型 @wraps

>>> help(fadd)

不被

extended(*args: ~T) -> ~T  

替换)。 T is not replaced by float ).


遇到的问题是 @wraps 装饰器无法更新类型提示,因为它旨在处理函数签名,而不是类型提示。为了解决这个问题,需要手动更新修饰函数的 __annotations__ 属性。

以下是如何更正装饰器以产生正确函数签名的示例:

from typing import Callable, TypeVar
from functools import reduce, wraps


T = TypeVar('T')


def extend(binop: Callable[[T, T], T]):
    """Extend a binary operator to multiple arguments."""

    @wraps(binop)
    def extended(*args: T) -> T:
        if not args:
            raise TypeError("At least one argument must be given")

        return reduce(binop, args)

    # 更新类型提示
    extended.__annotations__['args'] = tuple[T, ...]
    extended.__annotations__.pop('x', None)  # 删除旧的 'x' 注释
    extended.__annotations__.pop('y', None)  # 删除旧的 'y' 注释

    return extended

在这个改进后的版本中,我们添加了以下代码行:

    extended.__annotations__['args'] = tuple[T, ...]
    extended.__annotations__.pop('x', None)  # 删除旧的 'x' 注释
    extended.__annotations__.pop('y', None)  # 删除旧的 'y' 注释

这三行代码完成了以下操作:

  1. extended.__annotations__['args'] = tuple[T, ...] : 将 args 参数的类型提示更新为 tuple[T, ...] ,表示它可以接受任意数量的类型为 T 的参数。
  2. extended.__annotations__.pop('x', None) : 从 __annotations__ 字典中删除 x 键,因为修饰后的函数不再接受名为 x 的参数。
  3. extended.__annotations__.pop('y', None) : 从 __annotations__ 字典中删除 y 键,因为修饰后的函数不再接受名为 y 的参数。

通过手动更新类型提示,现在应该在使用 help(fadd) fadd.__annotations__ 时获得正确的函数签名和类型注释。

标签:python,python-typing,python-decorators
From: 62304871

相关文章

  • Python 类型提示:自引用类型检查
    我认为静态类型确实会让我在Python中的生活更轻松,考虑到我通常使用C语言工作。我创建了一个像这样的类:classnode(object):"""properties,constructor,etc."""defadd_outneighbor(self,neighbor:node)->None:"""d......
  • Python用shp文件裁剪多个遥感影像的方法
      本文介绍基于Python中ArcPy模块,基于矢量数据范围,对大量栅格遥感影像加以批量裁剪掩膜的方法。  首先,话不多说,本文所需要的代码如下所示。#-*-coding:utf-8-*-"""CreatedonTueDec1320:07:482022@author:fkxxgis"""importarcpyfromarcpy.saimport*......
  • 以编程方式删除 Python 源中的类型提示
    我有一些为Python3.5编写的源代码,我想使其在Python3.4下可执行。我使用的3.5中唯一在3.4中不可用的功能是类型提示,因此我想编写一个脚本来完全删除这些功能。乍一看这似乎很容易,我决定编写一些正则表达式这样做,但后来我想到了一些边缘情况,我不确定如何解决像这样的......
  • Python 类型暗示​​一个充满 myclass 对象的双端队列
    使用Python3.6或更高版本,我想输入提示一个返回MyClass对象的函数myfunc我如何提示myqueue是一个deque|||充满MyClass对象?objects?fromcollectionsimportdequeglobal_queue=deque()classMyClass:passdefmyfunc(m......
  • python之名称空间和作用域(关键字:global和nonlocal的使用)
    文章目录前言1、名称空间和作用域1.1引言1.2名称空间1.2.1内置名称空间1.2.2全局名称空间1.2.3局部名称空间1.2.4名称空间的产生和销毁顺序1.3作用域1.3.1全局作用域1.3.2局部作用域1.3.3名字的查找顺序1.4关键字:global1.5关键字:nonlocal前言本篇文章......
  • 用于 isinstance() 检查的 dict_keys 的显式 python3 类型是什么?
    在Python3中,我应该使用什么类型来检查字典键是否属于它?>>>d={1:2}>>>type(d.keys())<class'dict_keys'>所以我很自然地尝试了这个:>>>isinstance(d.keys(),dict_keys)Traceback(mostrecentcalllast):File"<stdin>",......
  • 初学Python时需要认识清楚的几个概念:对象、函数、圆括号给、点取、方括号取
    这是我在自学Python的过程中自己挑选和提炼出来的几个重要的概念,之所以特意介绍这些概念,其中包含了我自己的思维方式和我对Python设计理念的认识,有其独特性和局限性。我希望这篇文章能够给喜爱Python的朋友们带来一些启发。1、对象(Object)对象是Python编程的基本单元。就像音是......
  • 如何接受文件或路径作为python中方法的参数
    我正在尝试编写一个方法,该方法将接受打开的文件myFile=open("myFile.txt")obj.writeTo(myFile)myFile.close()或带有路径的字符串obj.writeTo("myFile.txt")该方法的实现如下:defwriteTo(self,hessianFile):ifisinstance(hessianFile,file):pr......
  • Python,“pathlib.Path.open()”方法和内置函数“open()”不返回“typing.IO”的实例
    我读过一些其他答案,它们似乎与现实生活中发生的事情相矛盾。尝试以下操作:fromtypingimportIOfrompathlibimportPathexample_path=Path(r"D:\Example.txt")withexample_path.open("r")asf:print(isinstance(f,IO))withopen(example_path)a......
  • 【Dison夏令营 Day 28】用 Python 创建恐龙游戏
    谁没有玩过谷歌著名的“恐龙游戏”?也许每个人都玩过这个游戏。今天,在这篇文章中,我们将帮助你用Python开发一个恐龙游戏。本教程将深入讲解每一行代码,并提供参考资料。我们将尽力让读者详细、透彻地理解这个项目。Python版恐龙游戏的任务记录包括图片文档和Python资料......