date: 2021-06-12title: Python函数介绍 #标题
tags: python #标签
categories: python # 分类

python中函数的使用场景一般常见于有大量重复代码,这样可以通过将重复代码定义为一个函数,当有需要时,直接调用函数即可,python也给我们提供了很多内置函数,比如len()、count()、open()…,关于函数的好处我们不多说,这篇博文主要是记录下函数相关的知识点。

函数传参的三种方式

我们在定义一个函数时,支持三种传参方式,分别是位置传参,关键字传参和混合传参,先来看看这三种方式的代码是什么样的:

  1. def my_info(name, age, sex, hight, weight):
  2. return '我叫{},年龄:{},性别{},身高:{},体重:{}'.format(name, age, sex, hight, weight)
  3. # 位置传参
  4. print(my_info('吕建钊', '18', '男', '175', '160'))
  5. # 关键字传参
  6. print(my_info(age='18', name='吕建钊', hight='175', sex='男', weight='160'))
  7. # 混合传参
  8. print(my_info('吕建钊', '18', hight='175', sex='男', weight='160'))
  9. # 打印结果如下
  10. 我叫吕建钊,年龄:18,性别男,身高:175,体重:160
  11. 我叫吕建钊,年龄:18,性别男,身高:175,体重:160
  12. 我叫吕建钊,年龄:18,性别男,身高:175,体重:160

三种传参方式的特性:

  • 位置参数:调用函数时,写参数必须按照顺序来写,不可以颠倒顺序;
  • 关键字参数:调用函数传参时,需要指明参数接收名字和值,对参数传入顺序没有要求
  • 混合传参:位置参数必须在关键字传参之前,并且位置参数顺序不能乱,后面关键字传参,对顺序没有要求。

什么是形参、实参

我们先来看一段代码:

  1. def my_info(name, age, sex, hight, weight):
  2. return '我叫{},年龄:{},性别{},身高:{},体重:{}'.format(name, age, sex, hight, weight)
  3. print(my_info('吕建钊', '18', '男', '175', '160'))

在上面的代码中,定义函数my_info的括号中的参数,就可以理解为是形参,而在下面print语句中调用函数时,传入的参数,就是实参。

函数的默认参数

我们在使用系统内置函数时,会发现有些函数的参数是可传可不传的,传参的话,需要使用关键字传参,所以不难发现,python内置的函数,大多数是属于混合传参的形式的,这里以open()函数为例:

  1. # open函数使用示例如下,可以看出来使用的是混合传参
  2. open('改文件测试',encoding='utf-8')
  3. # 我们可以看看open函数的定义:
  4. def open(file, mode='r', buffering=None, encoding=None, errors=None, newline=None, closefd=True): # known special case of open

上面就是open函数的定义,可以看到mode参数默认为r模式,也就是说,我们在使用open函数打开文件时,默认是以读的方式打开文件的,也是最常用的方式,所以才会设置默认值。

下面来一个带默认参数的函数示例:

  1. def my_info(name, age, hobby='唱歌'):
  2. return '我叫{},今年{}岁,爱好{}'.format(name, age, hobby)
  3. print(my_info('吕建钊', '18'))
  4. # 打印如下:
  5. 我叫吕建钊,今年18岁,爱好唱歌
  6. # 也可以传入hobby参数,覆盖默认值,如下:
  7. def my_info(name, age, hobby='唱歌'):
  8. return '我叫{},今年{}岁,爱好{}'.format(name, age, hobby)
  9. print(my_info('吕建钊', '18',hobby='跑步'))
  10. # 打印如下:
  11. 我叫吕建钊,今年18岁,爱好跑步

注意,如果设置了默认参数值,那么位置参数一定要在前面写,顺序不能乱,关键字参数写在位置参数后,对顺序没要求。

函数的万能参数

*args—接收所有位置参数

我们先来看一段代码:

  1. '''
  2. 在定义函数时,* 是将所有位置参数聚合到了一个元组中,然后赋值给了args这个变量
  3. '''
  4. def eat(*args):
  5. return '我想吃%s,%s,%s,%s,%s' % args
  6. print(eat('鸡', '鸭', '鱼', '猪肉', '白菜'))
  7. 打印如下:
  8. 我想吃鸡,鸭,鱼,猪肉,白菜

可以看到,一个*args接收了所有位置参数,这就是它的功能。

**kwargs—接收所有关键字参数

还是先来代码:

'''
在函数定义时,** 是将所有的关键字参数聚合到了一个字典中,然后赋值给了变量kwargs
'''
def eat(**kwargs):
    return kwargs


print(eat(food1='鸡', food2='鸭', food3='鱼', food4='猪肉', food5='白菜'))

args和kwargs的混合使用

如果代码如下:

def test(*args, **kwargs):
    return args, kwargs


l = [1, 2, 3, 4]
d = {'a': 1, 'b': 2}

如果我们在调用函数时,想将上述两个变量分别传给*args**kwargs,正常第一反应是这样写:

print(test(l, d))

# 打印如下:
(([1, 2, 3, 4], {'a': 1, 'b': 2}), {})

可以看到ld这两个变量,都赋值给了*args参数,而**kwargs参数打印出了一个空字典,那么,如果想达到我们想要的效果应该这样写:

print(test(*l, **d))

# 打印如下:
((1, 2, 3, 4), {'a': 1, 'b': 2})

万能参数和位置参数、关键字参数同时存在

如果你需要在函数中,同时定义位置参数、关键字参数、万能参数,那么请按照如下顺序:

def my_info(a,b,*args,sex='男',**kwargs):
    print(a)
    print(b)
    print(args)
    print(sex)
    print(kwargs)

my_info(1,2,3,4,5,sex='女',name='张三',hobby='跳舞')


# 打印结果如下:
1
2
(3, 4, 5)
女
{'name': '张三', 'hobby': '跳舞'}


# 上述代码,如果能看懂原理,就自己理解,不能的话,死记格式即可

调用函数时的函数聚合和函数打散

先看代码:

def fuc(*args):
    print(args)


fuc([11, 22], [33, 44])


# 打印如下:
([11, 22], [33, 44])

从上面代码输出结果可以看出,将传入的两个列表聚合到了一个列表中,那么我如果想要(11, 22, 33, 44)这样的效果呢?那就得用到函数调用时的聚合,正确代码如下:

def fuc(*args):
    print(args)

# 在元素前加一个*表示聚合
fuc(*[11, 22], *[33, 44])  # 等同于 fuc(11,22,33,44)

我们看到一颗*是这种效果,那么两颗*是什么效果呢?我们来看下面的代码:

def fuc(**kwargs):
    print(kwargs)


fuc(**{'name': '张三'}, **{'age': 18})  # 等同于fuc(name='张三',age=18)