Python 中的函数签名:详解与实例

news/2025/10/11 1:38:48/文章来源:https://www.cnblogs.com/wangya216/p/19134146

Python 中的函数签名:详解与实例

函数签名(Function Signature)在 Python 中是对函数调用接口的结构化描述,它定义了函数接收参数的方式、类型提示以及返回值信息。Python 的函数签名具有灵活性,不强制参数类型,但能清晰展示函数的使用规则。

一、函数签名的核心组成

Python 函数签名主要包含以下要素:

  • 函数名称
  • 参数列表(名称、类型注解、默认值、参数种类)
  • 返回值注解

我们可以使用标准库 inspect 模块的 signature() 函数来查看和分析函数签名。

二、不同类型的函数签名实例

1. 基础函数签名

最基本的函数签名包含必选参数和类型注解:

import inspectdef add(a: int, b: int) -> int:return a + b# 获取函数签名
sig = inspect.signature(add)
print(f"函数签名: {sig}")  # 输出: (a: int, b: int) -> int# 分析参数
for param in sig.parameters.values():print(f"参数名: {param.name}, 类型: {param.annotation}, 种类: {param.kind}")

输出:

函数签名: (a: int, b: int) -> int
参数名: a, 类型: <class 'int'>, 种类: POSITIONAL_OR_KEYWORD
参数名: b, 类型: <class 'int'>, 种类: POSITIONAL_OR_KEYWORD

2. 包含默认值的函数签名

当参数有默认值时,签名会明确标示:

def greet(name: str, greeting: str = "Hello") -> str:return f"{greeting}, {name}!"sig = inspect.signature(greet)
print(f"函数签名: {sig}")  # 输出: (name: str, greeting: str = 'Hello') -> strfor param in sig.parameters.values():print(f"参数名: {param.name}, 默认值: {param.default if param.default is not inspect.Parameter.empty else '无'}")

输出:

函数签名: (name: str, greeting: str = 'Hello') -> str
参数名: name, 默认值: 无
参数名: greeting, 默认值: Hello

3. 包含可变参数的函数签名

*args**kwargs 会在签名中特殊标示:

def sum_numbers(*args: int, multiplier: int = 1) -> int:return sum(args) * multipliersig = inspect.signature(sum_numbers)
print(f"函数签名: {sig}")  # 输出: (*args: int, multiplier: int = 1) -> intfor param in sig.parameters.values():print(f"参数名: {param.name}, 种类: {param.kind}")

输出:

函数签名: (*args: int, multiplier: int = 1) -> int
参数名: args, 种类: VAR_POSITIONAL
参数名: multiplier, 种类: KEYWORD_ONLY

4. 关键字-only 参数的函数签名

使用 * 分隔符可以定义关键字-only 参数:

def create_user(name: str, *, age: int, email: str) -> dict:return {"name": name, "age": age, "email": email}sig = inspect.signature(create_user)
print(f"函数签名: {sig}")  # 输出: (name: str, *, age: int, email: str) -> dictfor param in sig.parameters.values():print(f"参数名: {param.name}, 种类: {param.kind}")

输出:

函数签名: (name: str, *, age: int, email: str) -> dict
参数名: name, 种类: POSITIONAL_OR_KEYWORD
参数名: age, 种类: KEYWORD_ONLY
参数名: email, 种类: KEYWORD_ONLY

5. 位置-only 参数的函数签名

Python 3.8+ 支持使用 / 定义位置-only 参数:

def divide(a: float, b: float, /) -> float:return a / bsig = inspect.signature(divide)
print(f"函数签名: {sig}")  # 输出: (a: float, b: float, /) -> floatfor param in sig.parameters.values():print(f"参数名: {param.name}, 种类: {param.kind}")

输出:

函数签名: (a: float, b: float, /) -> float
参数名: a, 种类: POSITIONAL_ONLY
参数名: b, 种类: POSITIONAL_ONLY

6. 混合类型参数的函数签名

实际应用中,函数签名经常混合多种参数类型:

def complex_function(a: int,                  # 位置或关键字参数b: str,                  # 位置或关键字参数/,                       # 位置-only 参数结束标记c: float = 0.0,          # 关键字或位置参数(但在/后,只能关键字传入)*,                       # 关键字-only 参数开始标记d: bool = False,         # 关键字-only 参数**kwargs: str            # 可变关键字参数
) -> None:passsig = inspect.signature(complex_function)
print(f"函数签名: {sig}")for param in sig.parameters.values():print(f"参数名: {param.name}, 种类: {param.kind}")

输出:

函数签名: (a: int, b: str, /, c: float = 0.0, *, d: bool = False, **kwargs: str) -> None
参数名: a, 种类: POSITIONAL_ONLY
参数名: b, 种类: POSITIONAL_ONLY
参数名: c, 种类: POSITIONAL_OR_KEYWORD
参数名: d, 种类: KEYWORD_ONLY
参数名: kwargs, 种类: VAR_KEYWORD

三、函数签名的实际应用

1. 参数验证

可以使用函数签名在运行时验证参数是否符合要求:

def validate_arguments(func, *args, **kwargs):sig = inspect.signature(func)try:# 绑定参数并验证bound_args = sig.bind(*args, **kwargs)print("参数验证通过")return bound_argsexcept TypeError as e:print(f"参数错误: {e}")return None# 测试函数
def greet(name: str, age: int = 18) -> str:return f"Hello, {name} (age {age})"# 正确调用
validate_arguments(greet, "Alice", 30)  # 输出: 参数验证通过# 错误调用(类型不匹配,但Python本身不强制类型检查)
validate_arguments(greet, 123, "30")  # 输出: 参数验证通过(类型注解仅为提示)# 错误调用(参数数量不匹配)
validate_arguments(greet, "Bob", 25, "extra")  # 输出: 参数错误: too many positional arguments

2. 动态生成函数调用

函数签名可用于动态生成符合要求的函数调用:

def dynamic_call(func,** params):sig = inspect.signature(func)# 过滤掉函数不接受的参数valid_params = {k: v for k, v in params.items() if k in sig.parameters}return func(**valid_params)# 使用示例
def create_profile(name: str, age: int, city: str = "Unknown") -> dict:return {"name": name, "age": age, "city": city}# 传入额外参数会被过滤
data = {"name": "Charlie", "age": 35, "city": "New York", "extra": "ignored"}
print(dynamic_call(create_profile,** data))  # 输出: {'name': 'Charlie', 'age': 35, 'city': 'New York'}

四、总结

Python 的函数签名是函数接口的结构化描述,通过 inspect 模块可以方便地获取和分析。函数签名包含以下关键信息:

  • 参数名称和顺序
  • 参数类型注解(提示性)
  • 参数默认值
  • 参数种类(位置-only、位置或关键字、关键字-only、可变位置、可变关键字)
  • 返回值注解

函数签名的主要作用是:

  1. 明确函数的正确调用方式
  2. 支持 IDE 提供自动补全和类型提示
  3. 便于在运行时进行参数验证
  4. 为动态函数调用提供依据

理解和利用函数签名可以帮助我们编写更清晰、更健壮的代码,特别是在开发框架、装饰器或通用工具函数时非常有用。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/934505.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

基于AXI模块的视频流传输(上板移植篇)

先发泄一下,终于!!!国庆!一个国庆,你知道我怎么过的吗!!! 首先我是拿官方例程,但是还是依旧跑不通,检查一下,发现以下几个问题,并且我是怎么处理的: 1、首先上板失败,可能由于只是粗略配置了一下管脚没配…

装饰器工厂与类装饰器:进阶装饰器技术解析

装饰器工厂与类装饰器:进阶装饰器技术解析 装饰器是Python中强大的元编程工具,除多种进阶形式。其中装饰器工厂(Decorator Factory)和类装饰器(Class Decorator)是两种重要变体,分别解决“带参数的装饰器”和“…

53最大子数组和 动态规划和分制 - MKT

53最大子数组和 动态规划和分制 class Solution { public:// 时间不通过int maxSubArray_2(vector<int>& nums) {int tager_max=nums[0];int left=0;// sum_[i] map<int,int> sum_i; // 和 索引 由于…

Codeforces 2153D Not Alone 题解 [ 绿 ] [ 线性 DP ] [ 分类讨论 ]

Not Alone:唐题。 容易将题意转化为:环上的每一个颜色段长度都 \(\ge 2\),求最小操作数。 再考虑一个 \(O(n^2\log n)\) 的暴力,定义 \(dp_i\) 表示以 \(i\) 结尾的最小操作数,然后枚举前一个转移点 \(j\)。继续考…

__closure__:闭包的“身份证”

要理解“闭包函数和嵌套函数的区别在于 __closure__ 属性”,首先需要明确 嵌套函数 和 闭包函数 的基础关系——闭包函数是“满足特定条件的嵌套函数”,而 __closure__ 属性正是闭包函数区别于普通嵌套函数的“标志性…

Codeforces Round 1057 (Div. 2)

A. Circle of Apple Trees 题意:一个环形数组,每次到一个位置可以选择拿走这个元素或者跳过,然后走到下一个位置。每次拿的数要比之前拿的大,求最多拿多少数。 显然可以从小到大拿,那么答案就是不同数的个数。点击…

“表达式”(Expression)和“语句”(Statement)概念辨析

在编程中,“表达式”(Expression)和“语句”(Statement)是两个基础且容易混淆的概念。它们的核心区别在于是否有返回值以及在代码中的作用,以下从定义、特点、示例三个维度详细说明: 一、定义与核心区别表达式(…

每日一题 ###121买卖股票的最佳时机

仅以此记录所学所想,如有错误,还望指正。 首次尝试 1、我小小的脑子只能想出暴力解法,结果是超时了。 class Solution { public:int maxProfit(vector<int>& prices) {int max=0;for(int i=0;i<prices…

10.10总结

1.将一个数组中的值按逆序重新存放进行了编程联系,生成了对应程序 2.明天学习完善程序细节 3.今天收获满满

LibreChat-图文并茂手把手教你界面配置 | Adorable LibreChat Interface Configuration Guide

@目录🎀 整体介绍 | Overview🍪 配置项详解 | Field Details🎨 开关大全 | All Switches✨ 配置示例 | Cute ExampleConclusion | 结语 🎀 整体介绍 | Overview 今天我们来学习一下,LibreChat的页面基础配置哇…

GAE-广义优势估计算法介绍

一句话总结 GAE 就像「既要稳又要准」的聪明妥协:用多步 TD 误差加权平均,既缓解了 MC 的高方差,又减少了 TD 的单一偏差,通过调节参数(λ)灵活平衡两者的优缺点。MC vs TD 的痛点MC(蒙特卡洛):原理:跑完整个…

qemu模拟单片机

ESP32 乐鑫官方移植的qemu工程:espressif/qemu: Fork of QEMU with Espressif patches. See Wiki for details. 官方使用说明:esp-toolchain-docs/qemu/README.md at main espressif/esp-toolchain-docs 目前支持ES…

RAG-检索增强生成

检索增强生成(Retrieval-Augmented Generation, RAG)是近年来深度学习领域的重要技术突破,旨在解决大语言模型(LLM)在知识更新、事实准确性以及领域专业化方面的局限性。本文将从核心架构、功能实现、实践规范到高…

“猴子补丁”(monkey patch)跟猴子有关吗?

“猴子补丁”(monkey patch)指的是使函数名指向另一个函数。 这个名字里的“猴子”(monkey)和真实的动物猴子没有任何生物学或实体关联,它是编程领域的一个形象比喻,名字的由来与“猴子”的俚语含义有关。 为什么…

Yapi 使用docker在cenos7上部署教程与基本使用

✅ 前提条件 确保你已经完成以下准备:CentOS 7 系统已安装 Docker(未安装请先安装)拥有管理员权限(root 或 sudo)1、安装mongo数据库# 拉取mongo镜像,有本地镜像包可以直接导入 docker pull mongo # 安装mongo数…

C语言vsC++

一、核心区别设计理念C 语言:面向过程(Procedure-Oriented),以函数和数据结构为核心,强调算法和步骤的实现,关注 “怎么做”。 C++:基于 C 语言扩展而来,支持面向对象编程(Object-Oriented,OO),引入类、对…

20251010 之所思 - 人生如梦

20251010 之所思这两天想的事情有点多,有点焦虑,因为刚刚升职,部门的软件需要管理起来,已经不再仅仅管理自己现在的一个小组,今天看了一下软件的人数,数量已经到了122人,这是一个很庞大的队伍,如何管理好,心里…

2025.10.10

今天学生会开会导致十点没有回到宿舍 今天一节英语课,单词背诵情况不好,以后会加强 尝试轻食餐,不好吃

个人书单-从心流出发,学习积极心理学

从“心流”出发,构建你的积极心理学知识体系 | 专题书单 你是否曾有过这样的体验:在全神贯注地工作、运动或创作时,忘记了时间的流逝,内心充满了一种纯净而高效的愉悦感? 这就是米哈里契克森米哈赖所描述的 “心流…

等号(=)在C语言和python中有什么区别?

等号(=)在C语言和python中有什么区别? 等号(=)在 C 语言和 Python 中虽然核心功能都是“赋值”,但由于两种语言的设计理念(静态类型 vs 动态类型、编译型 vs 解释型)存在根本差异,= 的行为、特性和使用场景有…