首页 > 编程语言 >【Effective Python教程】(90个有效方法)笔记——第3章:函数——23:用关键字参数来传参(位置参数和关键字参数混合使用、默认参数值、万能形参**kwargs)强制关键字参数、可选参数

【Effective Python教程】(90个有效方法)笔记——第3章:函数——23:用关键字参数来传参(位置参数和关键字参数混合使用、默认参数值、万能形参**kwargs)强制关键字参数、可选参数

时间:2024-06-20 18:01:51浏览次数:31  
标签:传参 函数 位置 指定 关键字 参数 默认值

文章目录


Effective Python——编写高质量Python代码的90个有效方法

本书介绍:https://effectivepython.com/

代码demo:https://effectivepython.com/

第3章:函数

在这里插入图片描述

第23条 用关键字参数来传参

位置传递参数

与大多数其他编程语言一样,Python允许在调用函数时,按照位置传递参数(也就是按照参数列表所指定的顺序依次传递参数)。

在这里插入图片描述

def remainder(number, divisor):
    return number % divisor


assert remainder(20, 7) == 6

关键字传递参数

Python函数里面的所有普通参数,除了按位置传递外,还可以按关键字传递。

调用函数时,在调用括号内可以把关键字的名称写在=左边,把参数值写在右边。

这种写法不在乎参数的顺序,只要把必须指定的所有位置参数全都传过去即可。

位置和关键字传递参数混合使用

另外,关键字形式与位置形式也可以混用。下面这四种写法的效果相同:

在这里插入图片描述

如果混用,那么位置参数必须出现在关键字参数之前,否则就会出错。

在这里插入图片描述

每个参数只能指定一次,不能既通过位置形式指定,又通过关键字形式指定。

在这里插入图片描述

通过字典解包**my_kwargs传参

如果有一份字典,而且字典里面的内容能够用来调用remainder 这样的函数,那么可以把 ** 运算符加在字典前面,这会让 Python 把字典里面的键值以关键字参数的形式传给函数。

在这里插入图片描述

调用函数时,带 ** 操作符的参数可以和位置参数或关键字参数混用,只要不重复指定就行。

在这里插入图片描述

也可以对多个字典分别施加**操作,只要这些字典所提供的参数不重叠就好。

在这里插入图片描述

(这不就是参数解包吗?参考文章:Python 运算符(pythonkwargs:参数解包)(kwargs:keyword arguments))

函数定义万能形参**kwargs

定义函数时,如果想让这个函数接受任意数量的关键字参数,那么可以在参数列表里写上万能形参**kwargs,它会把调用者传进来的参数收集合到一个字典里面稍后处理。

(第26条讲了一种特别适合这么做的情况)。

在这里插入图片描述

def print_parameters(**kwargs):
    for key, value in kwargs.items():
        print(f'{key} = {value}')


print_parameters(alpha=1.5, beta=9, gamma=4)

print('*'*50)

my_kwargs = {
    'number': 2,
    'divisor': 7

}
print_parameters(**my_kwargs)

在这里插入图片描述

关键字参数好处

关键字参数的灵活用法可以带来三个好处。

第一个好处是,用关键字参数调用函数可以让初次阅读代码的人更容易看懂。

例如,读到remainder(20,7)这样的调用代码,就不太容易看出谁是被除数number,谁是除数divisor,只有去查看remainder的具体实现方法才能明白。

但如果改用关键字形式来调用,例如remainder(number=20,divisor=7),那么每个参数的含义就相当明了。

关键字参数的第二个好处是,它可以带有默认值,该值是在定义函数时指定的。

在大多数情况下,调用者只需要沿用这个值就好,但有时也可以明确指定自己想要传的值。这样能够减少重复代码,让程序看上去干净一些。

例如,我们要计算液体流入容器的速率。

如果这个容器带刻度,那么可以取前后两个时间点的刻度差(weight_diff),并把它跟这两个时间点的时间差(time_diff)相除,就可以算出流速了。

在这里插入图片描述

一般来说,我们会用每秒的千克数表示流速。

但有的时候,我们还想估算更长的时间段(例如几小时或几天)内的流速结果。

只需给同一个函数加一个period参数来表示那个时间段相当于多少秒即可。

在这里插入图片描述

这段代码中,period 参数使得函数可以根据用户定义的时间周期来调整流量计算。例如,如果想知道每小时的流量,可以将 period 设置为3600(秒数),这样就能得到小时平均流量。

这样写有个问题,就是每次调用函数时,都得明确指定period参数。即便我们想计算每秒钟的流速,也还是得明确指定period为1。

在这里插入图片描述
为了简化这种用法,我们可以给period参数设定默认值。

在这里插入图片描述
这样的话,period就变成可选参数了。

在这里插入图片描述

这个办法适用于默认值比较简单的情况。如果默认值本身要根据比较复杂的逻辑来确定(可参考第24条),那就得仔细考虑一下了。

关键字参数的第三个好处是,我们可以很灵活地扩充函数的参数,而不用担心会影响原有的函数调用代码。(有助于维护向后兼容)★★★★★

这样的话,我们就可以通过这些新参数在函数里面实现许多新的功能,同时又无须修改早前写好的调用代码,这也让程序不容易因此出现bug。

例如,我们想继续扩充上述flow_rate函数的功能,让它可以用千克之外的其他重量单位来计算流速。那只需要再添加一个可选参数,用来表示1千克相当于多少个那样的单位即可。

在这里插入图片描述

通过引入 units_per_kg 参数,进一步增加了 flow_rate 函数的灵活性。这个参数是用于将重量差异转换成其他单位,例如流体体积或者化学物质的摩尔数。这样做的目的是为了使函数更通用,可以适用于不同类型的流量计算。

units_per_kg 参数用于将重量(公斤)转换成其他单位。例如,如果你在测量水的流量,而设备提供的数据是以公斤为单位,你可能想要转换成升(L)。对于水,大约1公斤水等于1升。如果你想要计算每小时流过的升数,你可以将 units_per_kg 设置为1(表示1公斤水等于1升)。

新参数 units_per_kg的默认值为1,这表示默认情况下,依然以千克为重量单位来计算。

于是,以前写好的那些调用代码就不用修改了。

以后调用flow_rate 时,可以通过关键字形式给这个参数指定值,以表示他们想用的那种单位(例如磅,1千克约等于2.2磅)。

在这里插入图片描述

可选的关键字参数有助于维护向后兼容(backward compatibility)。

这是个相当重要的问题,对于接受带 *args 参数的函数,也要注意向后兼容(参见第22条)。

像 period 和 units_per_kg这样可选的关键字参数,只有一个缺点,就是调用者仍然能够按照位置来指定。

在这里插入图片描述

通过位置来指定可选参数,可能会让读代码的人有点儿糊涂,因为他不太清楚3600和2.2这两个值分别指哪个量的缩放系数。

所以,最好是能以关键字的形式给这些参数传值而不要按位置去传。从设计函数的角度来说,还可以考虑用更加明确的方案以降低出错概率(参见第25条)。

可参考:强制关键字参数*

要点

函数的参数可以按位置指定,也可以用关键字的形式指定

关键字可以让每个参数的作用更加明了,因为在调用函数时只按位置指定参数,可能导致这些参数的含义不够明确。

应该通过带默认值的关键字参数来扩展函数的行为,因为这不会影响原有的函数调用代码。

可选的关键字参数总是应该通过参数名来传递,而不应按位置传递。

在Python中,当我们谈论“可选的关键字参数总是应该通过参数名来传递,而不应按位置传递”时,我们是在强调代码的可读性和稳健性。关键字参数(Keyword arguments)是那些在函数调用时通过参数名明确指定的参数。这种方式的主要优点包括:

1. 提高代码可读性

使用关键字参数可以使函数调用更加明确和易于理解。例如,考虑以下函数定义和调用:

def register(name, age, is_student=False):
    pass

# 使用关键字参数调用
register(name="Alice", age=22, is_student=True)

在这个例子中,即使不查看 register 函数的实现,我们也能清楚地知道每个参数的意图和作用。对比如果按位置传递参数:

register("Alice", 22, True)

这里,True 的含义不够明确,除非查看函数定义。

2. 减少错误

当函数有多个参数,特别是多个可选参数时,使用关键字传递参数可以减少因位置错误导致的bug。例如:

def create_window(title, width=800, height=600, border=True, resizable=False):
    pass

# 使用关键字参数调用
create_window(title="My App", resizable=True, height=500)

通过关键字指定,我们可以安全地跳过某些默认参数,直接提供其他需要修改的参数,避免了位置错误。

3. 允许更灵活的函数签名变动

使用关键字参数的另一个好处是,当函数的参数列表在未来发生变化时,调用代码不太可能因此而中断。如果增加、删除或更改参数的默认值,使用关键字参数的函数调用通常不需要修改。

4. 强制关键字参数

在Python中,函数定义可以通过在参数前加 *(如 def func(*, key1, key2): pass)来强制使某些参数必须使用关键字参数形式传递。这种做法在函数接受多个参数或参数含义不明显时特别有用,有助于避免混淆和错误。


综上所述,通过参数名传递关键字参数是一种好的编程实践,它不仅使代码更清晰、安全,而且还提高了代码的灵活性和未来的可维护性。

Python函数的位置参数(position argument)与关键字参数(keyword argument)概念,默认参数值

在Python中,函数参数可以通过两种主要方式传递:位置参数和关键字参数。了解这两种类型的参数及其使用方式是掌握Python函数的关键部分。

位置参数

位置参数是最常见的参数类型,它们需要按照在函数定义中指定的顺序传递。例如,如果一个函数定义如下:

def func(a, b, c):
    print(a, b, c)

在调用func时,你必须按照a, b, c的顺序提供三个参数:

func(1, 2, 3)  # 输出: 1 2 3

如果参数的顺序或数量错误,Python将抛出错误。

关键字参数

关键字参数允许你在调用函数时指定参数名,这样参数的顺序就可以任意了。继续使用上面的例子,使用关键字参数的方式如下:

func(a=1, c=3, b=2)  # 输出: 1 2 3

这里,即使参数的顺序与定义中的不同,只要指明了参数名,函数依然可以正确地接收到所有的值。

混合使用位置参数和关键字参数(所有的位置参数必须位于任何关键字参数之前)

当你混合使用位置参数和关键字参数时,所有的位置参数必须位于任何关键字参数之前。例如:

func(1, b=2, c=3)  # 正确

但是,如下的调用将会导致错误:

func(b=2, 1, c=3)  # 错误,位置参数1不应该在关键字参数b之后

默认参数值

关键字参数常与默认参数值一起使用,这让函数调用更加灵活。例如:

def func(a, b=2, c=3):
    print(a, b, c)

在这个例子中,bc都有默认值,所以在调用时可以省略它们:

func(1)    # 输出: 1 2 3
func(1, c=4)  # 输出: 1 2 4

通过这种方式,可以根据需要只提供部分参数,其余参数使用定义时的默认值。

“关键字参数”跟“可选参数”不是同一回事!(可选参数是针对函数定义而言,关键字参数是针对函数调用而言)

关键字参数(keyword arguments)和可选参数(optional parameters)是两个相关但有区别的概念,在Python编程中经常被使用,但它们的含义并不完全相同:

关键字参数 (Keyword Arguments)

关键字参数指的是在函数调用时,通过参数名明确指定的参数。这意味着,无论参数在函数定义中的位置如何,都可以通过指定参数名称来传递参数值。关键字参数增加了代码的可读性和灵活性。

例如:

def print_details(name, age):
    print(f"Name: {name}, Age: {age}")

# 使用关键字参数调用
print_details(name="Alice", age=30)

在上述调用中,nameage 是通过关键字来指定的,它们是关键字参数。

可选参数 (Optional Parameters)

可选参数通常指的是在函数定义中通过为参数提供默认值来实现的参数。这意味着在调用函数时,可以选择不传递这些参数,函数会自动使用定义时给出的默认值。这类参数对于提供默认行为或设置非必需的配置很有用。

例如:

def log_message(level, message, timestamp=True):
    if timestamp:
        print(f"[{time.ctime()}] {level}: {message}")
    else:
        print(f"{level}: {message}")

# 可以选择不传递 timestamp 参数
log_message("INFO", "This is a log message.")

在上述定义中,timestamp 是一个可选参数,因为它有一个默认值 True

关系和区别

  • 关键字参数可以是可选的也可以是必需的。关键字参数的关键特性在于,参数是通过名称指定的,而不是通过位置。
  • 可选参数通常是通过为参数提供默认值来实现的,它们可以通过位置或关键字方式传递。

虽然可选参数往往是通过关键字传递(特别是当存在多个可选参数时),但它们不必总是关键字参数。可选参数的“可选”特性来自于它们有默认值,而关键字参数的特性是它们通过名称来指定。

标签:传参,函数,位置,指定,关键字,参数,默认值
From: https://blog.csdn.net/Dontla/article/details/139809651

相关文章

  • 技术革新引领钢材质量智能化检测新纪元,基于YOLOv3全系列【yolov3tiny/yolov3/yolov3sp
    随着人工智能(AI)技术的迅猛发展,其应用领域不断拓宽,正深刻改变着传统产业的运作模式。在钢材生产这一基础工业领域,AI的引入正为钢材的质量检测带来革命性的变革。在传统的钢材生产流程中,质量检测是确保产品质量的关键环节。然而,这一环节长期以来主要依赖于经验丰富的工人通过肉......
  • [转帖]HikariCP连接池参数解释
    https://www.cnblogs.com/wat1r/p/13710562.html ##数据库配置spring.datasource.type=com.zaxxer.hikari.HikariDataSourcespring.datasource.driverClassName=com.mysql.jdbc.Driverspring.datasource.url=jdbc:mysql://localhost:3306/ssm?useUnicode=true&chara......
  • 0基础学C++ | 第02天 | 基础知识 | sizeof关键字 | 浮点型 | 字符型 | 转义字符 | 字
    前言  该文章是在B站学习C++,同时结合自己的理解整理的笔记,视频连接:https://www.bilibili.com/video/BV1et411b73Z/?p=8&spm_id_from=333.880.my_history.page.click 1、sizeof关键字作用:利用sizeof关键字可以统计数据类型所占用的内存大小语法:sizeof(数据类型/变量)#incl......
  • java中的几个关键字
    在Java编程语言中,以下几个关键字扮演了重要角色,它们分别是this,static,super,Object和final。每个关键字都有其特定的用途和行为,理解这些关键字对于编写高效且可靠的Java代码至关重要。1.this关键字this关键字在Java中用来引用当前对象的实例。它有以下几种主要用途:引用......
  • 绝杀 GETPOST 嵌套的 JSON 参数
    JSON(JavaScriptObjectNotation)是一种轻量级的数据交换格式,常用于Web应用程序中的数据传输。在HTTP数据包信息传递时,JSON扮演着非常正常的角色,因为它是一种通用的数据格式,可以被多种编程语言和应用程序所支持。当客户端向服务器发送HTTP请求时,请求头中可以指定请求体的数据......
  • jquery 参数学习
    <!DOCTYPEhtml><htmllang="en"><head><metacharset="UTF-8"><metaname="viewport"content="width=device-width,initial-scale=1.0"><title>jquery使用</title>......
  • 鸿蒙内核源码分析(汇编传参篇) | 如何传递复杂的参数
    汇编如何传复杂的参数?汇编基础篇中很详细的介绍了一段具有代表性很经典的汇编代码,有循环,有判断,有运算,有多级函数调用。但有一个问题没有涉及,就是很复杂的参数如何处理?在实际开发过程中函数参数往往是很复杂的参数,(比如结构体)汇编怎么传递呢?先看一段C语言及汇编代码,......
  • Java设置JSON字符串参数编码
    1.如何在Java中创建JSON字符串在Java中创建JSON字符串,我们可以使用多个库,其中最流行的是Jackson、Gson和org.json。以下是使用这些库创建JSON字符串的示例:1.1使用Jackson库(1)首先,确保我们的项目中包含了Jackson的依赖(如果我们使用Maven,可以参考前面的示例)。(2)创建一个Java对象(例......
  • 【物理应用】用于建模双相阵声悬浮器所需参数的声学换能器矩阵产生的压力APP
     ✅作者简介:热爱科研的Matlab仿真开发者,修心和技术同步精进,代码获取、论文复现及科研仿真合作可私信。......
  • 【扩散映射+线性卡尔曼滤波+Koopman算子】一种用于高维非线性随机动力系统状态估计的
     ......