14、Python之super star:一颗星、两颗星,满天都是小星星

news2024/11/15 13:47:17

引言

关于Python系列的文章,已经通过两篇文章,介绍了Python中关于函数的简单使用,包括为什么要使用函数,以及函数中带默认值参数的使用注意事项。

之后,岔开函数的主题,通过几篇番外篇,重点谈了一下Python中一切皆对象、Python的数据模型,以及Python中函数和类也是一等公民的理念。其实,关于函数也一直有所涉及。

今天,准备结合Python中星号(star)操作符的用法,继续展开Python中函数的介绍。

关于星号(*)的使用,主要内容有:

1、基础的乘法运算
2、字符串的重复
3、列表的扩充
4、定义不定长的函数位置参数
5、函数调用时,将列表拆包为位置参数进行传递
6、定义不定长的函数关键字参数
7、函数调用时,将字典拆包为关键字参数进行传递

python中的乘法运算

*号是所有编程语言中,比较常见的操作符,首先能够想到的就是四则运算中的乘法运算。没错,首次接触编程语言的新手,可能在键盘上找不到表示乘法运算的x。在所有编程语言中,都是使用*的。

# *的基础作用,乘法运算:
a = 10
b = 5
print(f"{a}乘以{b}的结果是:{a * b}")

# Python中也支持复合赋值的操作:
# 等价于 b = b * 100
b *= 100
print(b)

执行结果:

除了数字可以进行乘法运算,Python中将乘法运算进行了扩充:
字符串可以与数字进行相乘,进行字符串的重复

# 书读百遍,其义自现;百遍太多,十遍也行
s1 = 'Life is short, I use Pyton\n'
s2 = s1 * 10
print(s2)

执行结果:

列表也可以进行乘法运算的扩充:

# 一个不过瘾,我要打十个
enemies = ['小喽啰']
print(id(enemies))
enemies *= 10
print(id(enemies))
print(enemies)

执行结果:


这里的复合赋值操作,实际上进行了原列表对象的扩充,而非重新构造一个列表对象。

自动打包

在前面的文章中,介绍Python的unpacking机制时,已经用到过*号,将不需要的元素进行装包,这里简单回顾一下:

# * unpacking
persons = [('张三', 18, 190, '女'), ('小红', 23, 165, '男')]
for p in persons:
    name, *others, gender = p
    print(others)
    print(type(others))
    print(f"姓名: {name}, 性别: {gender}")


还是,之前的代码,我们通过*号修饰others变量,从而将除了name、gender接收的元素外,统一打包为一个列表,交由others变量来进行接收:

函数中的位置参数

相较于其他编程语言中的函数调用,形参列表和实参列表必须一一对应,按顺序传递(默认值参数除外)。Python中将必须按照顺序一一传递的函数调用传参,称为位置参数:

a = 10
b = 5
result = divide(a, b)
print(f"{a}除以{b}的结果是:{result}")

我们很容易碰到的一个问题是,如何定义一个函数,可以接收不定数目的参数,比如以下实际场景:
我们如何定义一个函数,可以计算若干个数字的和?
在其他编程语言中,可以通过函数重载来实现,可以定义多个同名的函数,但是参数列表的参数类型、个数不同。
但是,Python中似乎不支持函数重载。

很容易想到的一个变通的解法是我们定义一个接收一个列表作为参数的函数,列表中有几个元素,就是对几个元素求和:

# 定义一个接收列表的函数,从而变通地实现不定数目的参数求和
def my_sum(args):
    result = 0
    for num in args:
        result += num
    return result


nums = [1, 2, 3, 4, 5]
print(my_sum(nums))

这样,确实能够实现不定长参数的问题,但是,每次调用函数,都必须包装成一个列表,然后才能进行传参,似乎有点不太方便。

不定长位置参数

其实,Python中有更好的解决方案:通过*号,让函数接收数量可变的位置参数,可以让函数的设计、使用更加清晰。

这些位置参数通常简称为varargs,或者叫作star args,因为在Python中,我们习惯于使用*args来进行数量可变的位置参数的定义(注意,只是习惯,可以是别的命名方式)。

接下来,还是关于数字求和的问题,我们看star args的函数定义方式:

# 定义star args的函数,实现不定数目的参数求和
def my_sum(*args):
    result = 0
    for num in args:
        result += num
    return result


# 函数调用
print(my_sum(1, 2, 3, 4, 5))

可以发现,只需要将原来的函数定义的地方,参数前面加个*就可以解决这个问题了。

函数的调用方式,变成了直接传具体的数字就行了,有多少传多少,不需要包装成列表对象了。

如果由于历史原因,已经将参数包装成列表了,怎么办呢,也可以通过调用时加*进行unpacking处理:

# 定义star args的函数,实现不定数目的参数求和
def my_sum(*args):
    result = 0
    for num in args:
        result += num
    return result


# 列表调用
nums = [1, 2, 3, 4, 5]
print(my_sum(*nums))

不定长的star args,也可以跟固定的位置参数混合使用:

# 定义star args的函数,实现不定数目的参数求和
def my_sum(initial_value, *args):
    result = initial_value
    for num in args:
        result += num
    return result


# 列表调用
nums = [1, 2, 3, 4, 5]
print(my_sum(100, *nums))

有些教材中,描述说固定的位置参数必须放在star args之前进行定义,这种说法其实是不严谨的。

这两种参数,可以理解为一个是必选的参数,另一个是可选的参数。由于都是按照位置来传,就没法区分,哪个是由必选参数接收,哪个又是由可选参数接收了。

Python中,通过关键字参数机制来避免位置参数传参的二义性。

函数中的关键字参数

由于通过位置参数进行传参,必须顺序一一对应,稍不留神,可能就会导致错误,而且后续函数扩展,增加新的位置参数,所有调用的地方都要按照顺序调整……

好在Python中除了位置参数的函数调用方式,还可以通过关键字进行传参,可以避免位置错乱的问题,回到前面的除法的函数:

# 简单的关键字参数调用演示
def divide(a, b):
    return a / b


# 我们都一样
print(divide(10, 5))
print(divide(10, b=5))
print(divide(a=10, b=5))
print(divide(b=5, a=10))

回到上面关于数量不定的位置参数,并不是star args后面,就不能定义必选参数了,只是调用时需要使用关键字参数进行调用而已。

所以,Python中关于函数参数定义的规定是:在star args之后定义的参数,都是关键字参数,调用的时候,只能使用关键字参数的方式进行参数传递:

# 定义star args的函数,实现不定数目的参数求和
def my_sum(*args, initial_value):
    result = initial_value
    for num in args:
        result += num
    return result


# 列表调用
nums = [1, 2, 3, 4, 5]
# 这种定义方式会报错,可以清晰地看到不定长位置参数与关键字参数混用的限制
print(my_sum(*nums, 100))

运行报错:


必须以关键字参数的形式传递initial_value这个参数。正确的调用方式:

print(my_sum(*nums, initial_value=100))
print(my_sum(initial_value=100, *nums))

从Python 3.8开始,哪怕函数不需要不定长的位置参数,也可以在函数定义中,使用*号,来强制要求之后的参数必须作为关键字参数进行传参:

# Python3.8开始的,*使用

def star_func(a, b, *, c, d):
    print(f"a: {a}, b: {b}, c: {c}, d:{d}")


# 报错 TypeError: star_func() takes 2 positional arguments but 4 were given
# star_func(1, 2, 3, 4)

# 报错 TypeError: star_func() missing 2 required keyword-only arguments: 'c' and 'd'
# star_func(1, 2)

# 正确调用方式:
star_func(1, 2, d=10, c=5)

不定长关键字参数

位置参数可以不定数目,实现函数的一次定义,灵活调用。关键字参数,其实也是可以的。这就是要介绍的两颗星的使用了(**)

在Python函数定义中的两个习惯:

  • *args:进行不定长的位置参数的定义
  • **kwargs:进行不定长的关键字参数的定义

再次说明,只是习惯,args、kwargs的参数名是可以随意的。

以一个简单的示例说明下不定长关键字参数的定义:

def double_star_func(**kwargs):
    print("传递的关键字参数有:")
    for key, value in kwargs.items():
        print(f"key: {key}, value: {value}")


double_star_func(a=1, b=2, c='hello python')
double_star_func(host='127.0.0.1', port=3306, user='deploy', database='test')

此外,如同我们可以通过列表来进行位置参数的传递,关键字参数,我们可以通过字典对象进行传递。

通过将我们已有的存储在字典中的配置信息,以关键字参数的方式进行传递,可以极大地简化函数的调用。

比如,有如下场景,我们需要进行MySQL的数据库连接,我们以字典对象的方式存储了多个数据库的连接配置信息:

第一种连接数据库的函数调用方式:

import pymysql

db_configs = {
    'dev': {
        'host': '127.0.0.01',
        'port': 3306,
        'user': 'dev_user',
        'password': 'dev_password',
        'database': 'db_dev'
    },
    'test': {
        'host': '127.0.0.01',
        'port': 3306,
        'user': 'test_user',
        'password': 'test_password',
        'database': 'db_test'
    },
    'prod': {
        'host': '127.0.0.01',
        'port': 3306,
        'user': 'prod_user',
        'password': 'prod_password',
        'database': 'db_prod'
    }
}

dev_db = db_configs['dev']
db_conn = pymysql.connect(host=dev_db['host'], port=dev_db['port'], user=dev_db['user'], password=dev_db['password'], database=dev_db['database'])


有点麻烦……
第二种连接方式:我们看是用字典传参的方式:

import pymysql

db_configs = {
    'dev': {
        'host': '127.0.0.01',
        'port': 3306,
        'user': 'dev_user',
        'password': 'dev_password',
        'database': 'db_dev'
    },
    'test': {
        'host': '127.0.0.01',
        'port': 3306,
        'user': 'test_user',
        'password': 'test_password',
        'database': 'db_test'
    },
    'prod': {
        'host': '127.0.0.01',
        'port': 3306,
        'user': 'prod_user',
        'password': 'prod_password',
        'database': 'db_prod'
    }
}

db_conn = pymysql.connect(**db_configs['dev'])

在函数调用时,可以通过两个星号(**)来将字典解析为函数的关键字参数进行传递,从而简化函数的调用。

总结

在Python中,星号(*)的主要用法有:

1、基础的乘法运算
2、字符串的重复
3、列表的扩充
4、定义不定长的函数位置参数
5、函数调用时,将列表拆包为位置参数进行传递
6、定义不定长的函数关键字参数
7、函数调用时,将字典拆包为关键字参数进行传递

只要理解了这几点,在后续的使用中,就能大大简化自己代码的编写,真正提高代码的编写效率,毕竟我们选择用Python的原因在于人生苦短。

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

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

相关文章

PHP恋爱话术微信小程序系统源码

💖恋爱高手的秘密武器!恋爱话术微信小程序,让情话信手拈来✨ 💭【开场白:恋爱路上的甜蜜助手】💭 还在为跟心仪的TA聊天时找不到话题而尴尬?或是担心自己说的每句话都显得那么“直男/女”&…

YOLOv8改进 | 检测头 | 融合渐进特征金字塔的检测头【AFPN3】

秋招面试专栏推荐 :深度学习算法工程师面试问题总结【百面算法工程师】——点击即可跳转 💡💡💡本专栏所有程序均经过测试,可成功执行💡💡💡 专栏目录 :《YOLOv8改进有效…

文件安全传输系统,如何保障信创环境下数据的安全传输?

文件安全传输系统是一套旨在保护数据在传输过程中的安全性和完整性的技术或解决方案。通常包括以下几个关键组件: 加密:使用强加密算法来确保文件在传输过程中不被未授权访问。 身份验证:确保只有授权用户才能访问或传输文件。 完整性校验…

数据库管理-第220期 Oracle的高可用-03(20240715)

数据库管理220期 2024-07-15 数据库管理-第220期 Oracle的高可用-03(20240715)1 AC/TAC2 配置Service3 用户权限4 端口开放总结 数据库管理-第220期 Oracle的高可用-03(20240715) 作者:胖头鱼的鱼缸(尹海文…

量化发展历史简述,QMT/PTrade+恒生UFT、LDP极速柜台适用哪些情形?

量化发展简述 1.2004年萌发阶段:策略局限在量化择时,量化选股等; 光大保德信量化核 心基金 上投摩根阿尔法基 金 金融危机,海归引入。 2.2010量化元年:中低频交易为主,主要依靠套利、对冲、多因子策略等…

****react的antdesign 下拉组件ProFormSelect编辑首次不回显问题

1、使用valueEnum无法自动回显 2、要使用options会自动回显

AutoMQ 社区双周精选第十二期(2024.06.29~2024.07.12)

本期概要 欢迎来到 AutoMQ 第十一期双周精选!在过去两周里,主干动态方面,AutoMQ 跟进了 Apache Kafka 3.4.x BUG 修复,并进行了CPU & GC 性能优化,另外,AutoBalancing 的 Reporter 和 Retriever 也将支…

风险评估:IIS的安全配置,IIS安全基线检查加固

「作者简介」:冬奥会网络安全中国代表队,CSDN Top100,就职奇安信多年,以实战工作为基础著作 《网络安全自学教程》,适合基础薄弱的同学系统化的学习网络安全,用最短的时间掌握最核心的技术。 这一章节我们需…

51单片机5(GPIO简介)

一、序言:不论学习什么单片机,最简单的外设莫过于I口的高低电平的操作,接下来,我们将给大家介绍一下如何在创建好的工程模板上面,通过控制51单片机的GPIO来使我们的开发板上的LED来点亮。 二、51单片机GPIO介绍&#…

实验二:图像灰度修正

目录 一、实验目的 二、实验原理 三、实验内容 四、源程序和结果 源程序(python): 结果: 五、结果分析 一、实验目的 掌握常用的图像灰度级修正方法,包括图象的线性和非线性灰度点运算和直方图均衡化法,加深对灰度直方图的理解。掌握对比度增强、直方图增强的原理,…

C++相关概念和易错语法(21)(虚函数、协变、析构函数的重写)

多态的核心是虚函数&#xff0c;本文从虚函数出发&#xff0c;根据原理慢慢推进得到结论&#xff0c;进而理解多态 1.虚函数 先看一下下面的代码&#xff0c;想想什么导致了这个结果 #include <iostream> using namespace std;class A { public:virtual void test(){co…

书生实战营-LLM实战笔记

训练营非常好&#xff0c;有个github上的tutorial Tutorial/docs/L0/Linux/readme.md at camp3 InternLM/Tutorial GitHub 第1关卡 linux 的基础知识 https://github.com/InternLM/Tutorial/blob/camp3/docs/L0/Linux/readme.md#linuxinternstudio-%E5%85%B3%E5%8D%A1 非…

AIGC笔记--基于Stable Diffusion实现图片的inpainting

1--完整代码 SD_Inpainting 2--简单代码 import PIL import torch import numpy as np from PIL import Image from tqdm import tqdm import torchvision from diffusers import AutoencoderKL, UNet2DConditionModel, DDIMScheduler from transformers import CLIPTextMod…

【全面介绍Pip换源】

&#x1f3a5;博主&#xff1a;程序员不想YY啊 &#x1f4ab;CSDN优质创作者&#xff0c;CSDN实力新星&#xff0c;CSDN博客专家 &#x1f917;点赞&#x1f388;收藏⭐再看&#x1f4ab;养成习惯 ✨希望本文对您有所裨益&#xff0c;如有不足之处&#xff0c;欢迎在评论区提出…

产品经理-产品经理会在项目中遇到的几个问题(16)

项目中遇到了需求变更怎么办&#xff1f; 首先要弄清楚需求变更的原因是什么。如果是因为在迭代的过程中更好地理解了用户需求 进而产生了更好的需求则完全是正常的。如果是因为老板的需求 那就需要和老板沟通清楚&#xff0c;并且确保自己能理解老板的需求&#xff0c;而且这个…

【数据结构】高效解决连通性问题的并查集详解及Python实现

文章目录 1. 并查集&#xff1a;一种高效的数据结构2. 并查集的基本操作与优化2.1 初始化2.2 查找操作与路径压缩2.3 合并操作与按秩合并 3. 并查集的应用3.1 判断连通性3.2 计算连通分量 4. 并查集的实际案例4.1 图的连通性问题4.2 网络连接问题 5. 并查集的优缺点5.1 优点5.2…

哪些网站是获取独立站外链的最佳选择?

想要为独立站获取外链&#xff0c;有几个地方可以考虑&#xff0c;首先自然是最有效的博客和文章投稿网站&#xff0c;找那些与你的行业相关的博客和内容平台&#xff0c;撰写高质量的文章&#xff0c;里面自然地嵌入你的链接。这是最有价值的外链 然后不分其他&#xff0c;效…

ESP32-S3多模态交互方案在线AI语音设备应用,启明云端乐鑫代理商

随着物联网&#xff08;IoT&#xff09;和人工智能&#xff08;AI&#xff09;技术的飞速发展&#xff0c;嵌入式设备正逐渐变得智能化&#xff0c;让我们的家庭生活变得更加智能化和个性化。 随着大型语言模型的不断进步和优化&#xff0c;AI语音机器人设备能够实现更加智能、…

超越 Transformer开启高效开放语言模型的新篇章

在人工智能快速发展的今天&#xff0c;对于高效且性能卓越的语言模型的追求&#xff0c;促使谷歌DeepMind团队开发出了RecurrentGemma这一突破性模型。这款新型模型在论文《RecurrentGemma&#xff1a;超越Transformers的高效开放语言模型》中得到了详细介绍&#xff0c;它通过…

软件工程课设——成绩管理系统

软件工程课设——成绩管理系统 该文档是软件工程课程设计&#xff0c;成绩管理子系统的开发模块仓库。 功能分析 从面向的用户分&#xff0c;成绩管理子系统主要面向三类用户&#xff0c;即至少需要满足这三类用户的需求&#xff1a; 学生&#xff1a;学生是成绩管理系统的…