Python编程思想(19):可变参数也可以这样玩

李宁老师已经在「极客起源」 微信公众号推出《Python编程思想》电子书,囊括了Python的核心技术,以及Python的主要函数库的使用方法。读者可以在「极客起源」 公众号中输入 160442 开始学习。

《Python编程思想》总目录

《Python编程思想》专栏

1. 为函数传递无限多个参数

很多编程语言都允许定义个数可变的参数,这样可以在调用函数时传入任意多个参数。 Python当然也不例外,Python允许在形参前面添加一个星号(*),这样就意味着该参数可接收多个参数值,多个参数值被当成元组传入。下面程序定义了一个形参个数可变的函数。

示例代码:var_args.py

# 定义了支持可变参数的函数
def test(n, *books) :
    print(books)
    # books被当成元组处理
    for b in books :
        print(b)
    # 输出整数变量n的值
    print(n)
# 调用test()函数
test(10 , "Python从菜鸟到高手" , "Python爬虫")

运行上面程序,将看到如下运行结果:

('Python从菜鸟到高手', 'Python爬虫')
Python从菜鸟到高手
Python爬虫
10

从上面的运行结果可以看出,当调用 test()函数时,books参数可以传入多个字符串作为参数值。从 test()的函数体代码来看,可变参数的本质就是一个元组。Python会将传给 books参数的多个值放在一个元组里。

Python允许个数可变的形参可以处于形参列表的任意位置(不要求是形参列表的最后一个参数),但 Python要求一个函数最多只能带一个支持可变参数的形参。例子程序如下:

示例代码:var_args1.py

# 定义了支持参数收集的函数
def test(*books ,num) :
    print(books)
    # books被当成元组处理
    for b in books :
        print(b)
    print(num)
# 调用test()函数
test("Python从菜鸟到高手", "Android完全讲义", num = 123)

my_list = ["微信小程序开发入门精要", "Android权威指南"]
# 将列表的多个元素传给支持参数收集的参数
test(my_list, num = 120)
my_tuple= ("Python从菜鸟到高手", "Android完全讲义")
# 将元组的多个元素传给支持参数收集的参数
test(*my_tuple, num = 12)

运行这段代码,会输出下面的结果:

('Python从菜鸟到高手', 'Android完全讲义')
Python从菜鸟到高手
Android完全讲义
123
(['微信小程序开发入门精要', 'Android权威指南'],)
['微信小程序开发入门精要', 'Android权威指南']
120
('Python从菜鸟到高手', 'Android完全讲义')
Python从菜鸟到高手
Android完全讲义
12

正如从上面程序中所看到的,tes()函数的第1个参数就是个数可变的形参,由于该参数可接收个数不等的参数值,因此如果需要给后面的参数传入参数值,则必须使用关键字参数,否则,程序会把所传入的多个值都传给 books参数。Python还可以收集关键字参数,此时 Python会将这种关键字参数收集成字典。为了让 Python能收集关键字参数,需要在参数前面添加两个星号(**)。在这种情况下,一个函数可同时包含一个支持“普通”参数收集的参数和一个支持关键字参数收集的参数。例如如下代码

示例代码:var_args2.py

# 定义了支持参数收集的函数
def test(x, y, z=10, *books, **scores) :
    print(x, y, z)
    print(books)
    print(scores)
test(1, 2, 3, "Python从菜鸟到高手" , "Python爬虫", English=79, 高等数学=99)
test(4, 6, "Android完全开发讲义" , "Android权威指南", Chinese=97, 物理=68)
test(3, 7, 绘画=45, 音乐=78)

运行这段代码,会输出如下的内容:

1 2 3
('Python从菜鸟到高手', 'Python爬虫')
{'English': 79, '高等数学': 99}
4 6 Android完全开发讲义
('Android权威指南',)
{'Chinese': 97, '物理': 68}
3 7 10
()
{'绘画': 45, '音乐': 78}

对于上面代码中定义的 test()函数,参数z的默认值几乎不能发挥作用。比如按如下方式调用test()函数。

test(1,2,"Python从菜鸟到高手","Python爬虫",Chinese=90,Maths=100)

上面代码在调用 test()函数时,前面的1、2、"Python从菜鸟到高手"将会传给普通参数x、y、z,接下来的一个字符串将会由 books参数收集成元组。最后的两个关键字参数将会被收集成字典。运行上面代码,会看到如下输出结果。

1 2 Python从菜鸟到高手
('Python爬虫',)
{'Chinese': 90, 'Maths': 100}

如果希望让z参数的默认值发挥作用,则需要只传入两个位置参数。例如代码如下:

test(1,2,语文=90,数学=80)

上面代码在调用test()函数时,前面的1和2将会传给普通参数x、y,此时z参数将使用默认的参数值10, books参数将是一个空元组。接下来的两个关键字参数将会被收集成字典。运行上面代码,会看到如下输出结果。

1 2 10
()
{'语文': 90, '数学': 80}

2. 将集合拆成单个元素

将集合拆成单个元素,指的是在程序已有列表、元组、字典等对象的前提下,把它们的元素“拆开”后传给函数的参数。逆向参数收集需要在传入的列表、元组参数之前添加一个星号,在字典参数之前添加两个星号。

示例代码:var_args3.py

def test1(name, message):
    print(f"name: {name}")
    print(f"message: {message}")


my_list = ['雷神', '欢迎来到地球']
test1(*my_list)


def test2(name, *nums):
    print(f"name参数:{name}")
    print(f"nums参数: {nums}" )


my_tuple = (1, 2, 3)
# my_tuple元组的元素传给nums参数
test2('hello', *my_tuple)

# 将my_tuple元组的第1个元素传给name参数,剩下参数传给nums参数
test2(*my_tuple)

# my_tuple元组整体传给name参数
test2(my_tuple)


def test3(book, price, desc):
    print(book, f"price: {price}")
    print(f'desc:{desc}', desc)


my_dict = {'price': 128, 'book': 'Python从菜鸟到高手', 'desc': '这是一本全面介绍Python的书'}
# 将my_dict的多个key-value传给bar()函数
test3(**my_dict)

运行这段代码,会输出如下的结果:

name: 雷神
message: 欢迎来到地球
name参数:hello
nums参数: (1, 2, 3)
name参数:1
nums参数: (2, 3)
name参数:(1, 2, 3)
nums参数: ()
Python从菜鸟到高手 price: 128
desc:这是一本全面介绍Python的书 这是一本全面介绍Python的书

我们可以看到,如果不加星号(*),那么元组会被当做一个值传入函数,如果加星号(*),那么就会将该元组拆开,每一个元素都会作为独立的值传入函数。

上面第一行代码先使用位置参数为name参数传入参数值,再使用关键字参数为 message参数。

 

-----------------支持作者请转发本文,也可以加李宁老师微信:unitymarvel,或扫描下面二维码加微信--------

欢迎关注  极客起源  微信公众号,更多精彩视频和文章等着你哦!

猜你喜欢

转载自blog.csdn.net/nokiaguy/article/details/106899988
今日推荐