函数
函数(function)就是用于完成特定功能的代码块
使用函数的原因:
- 增强代码的复用性
- 封装代码的实现,保护数据的安全
函数的创建
在python中定义函数要使用关键字
def
,使用return 表达式
返回内容在函数定义的过程中要注意:
- 函数定义要以
def
开头,一个空格后跟函数名和圆括号()
,再接冒号- 任何参数的传入要写在圆括号里面,多个参数要以 逗号(
,
)间隔- 函数的内容以冒号开始,函数内的代码要保持缩进一致
- 函数
return
结束,没有return
执行最后一行结束,默认放回None
。
格式:
def 函数名(参数列表):
# 函数体
# 代码实现
return 表达式
例子:
>>> def sum(num1,num2):
... return num1 + num2
...
函数的调用
函数存在的目的就是被调用,想要调用一个函数就要以函数名加圆括号的形式进行调用,想要正确的调用一个函数除了函数名要正确外,参数列表必须要一一对应,否则会报错
>>> sum(1)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: sum() missing 1 required positional argument: 'num2'
>>> sum('a', 2)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 2, in sum
TypeError: can only concatenate str (not "int") to str
>>> sum(1,2)
3
sum(num1,num2)
函数我们需要两个int类型参数,如果给一个,就会报错,给的类型不对也会报错,只有数量和类型都没问题才会运行这个函数.
函数的参数
函数通常都有参数,用于将外部数据的传入函数内部进行处理。
python函数的参数有5种:
- 位置参数(positional arguments,官方定义,相当于其他编程语言的参数)
- 默认参数(类似与C++的默认参数)
- 动态参数
- 关键字参数
传入不同的参数会有不同的结果发送
def change_num(num):
num += 1
print(num)
num = 0
change_num(num)
print(num)
----------------------------------
1
0
def change_num(num_list):
num_list.append(1)
num_list = [1,2]
print(num_list)
change_num(num_list)
print(num_list)
----------------------------------
[1, 2]
[1, 2, 1]
为什么?
因为,Python的数据类型分可变数据类型和不可变数据类型。
num
是一个不可变对象一旦你改变num
的值,num
就会创建一个新的数字对象
Python的函数参数传递的是实际对象的内存地址。外部num
和内部num
指向同一地址, 但是改变参数num
的值的时候,会使它指向一个新的内存空间,但是外部num
指向的内存地址不会被改变。
list
是可变的数据类型
传递参数时,先将实际参数列表
的地址传参数num_list
函数内通过参数num_list
改变list内的值时,并不会创建新的内存空间后操作,而是直接在原有的内存空间中进行操作,这要的话,你在函数内对列表的修改实际就是作用在原对象上
-
位置参数
位置参数就是其他语言的参数,所有参数都要遵循位置一一对应的原则
def max_min(a, b, c): lis = [a, b, c] min = lis[0] max = 0 for i in lis: if i > max: max = i if i < min: min = i return min, max print(max_min(2, 1, 3)) ---------------------------------- (1, 3) # 由此可见当return返回多个参数时,会将数据封装为一个元组对象
-
默认参数
python的默认参数完全等同于C++的默认参数,引入默认参数是为了在某些情况向提供便利
语法:
形参名 = 默认值
def print_info(name, age, sex='女'): print(name + '-->' + str(age) + '--->' + sex) print_info('剑姬', 18) print_info('剑魔', 20, '男')
默认参数的优势:如果在男女比例均衡的地方,和普通参数一致,但是如果出现只有男或女,默认对象会有很大的优势
使用时注意点:
-
默认参数要写在最右端,不然会产生歧义(编译不通过)
>>> def print_info(sex='女', name, age): File "<stdin>", line 1 def print_info(sex='女', name, age): ^ SyntaxError: non-default argument follows default argument
-
默认参数一定要是不可变对象(int、float、str、tuple)
def list_default(lis = []): lis.append('Python') return lis print(list_default()) print(list_default()) ---------------------------------- ['Python'] ['Python', 'Python']
python不会将默认参数使用后直接释放,多次调用含默认参数的函数,就会对参数进行多次修改
改进方法使用
None
:def list_default(lis=None): if lis is None: lis = [] lis.append('Python') return lis print(list_default()) print(list_default()) ---------------------------------- ['Python'] ['Python']
-
-
动态参数
动态参数顾名思义,就是传入的参数的个数是动态的,python的动态参数分两种,分别是
*args
和**kwargs
,它们的区别是一个*
和两个*
的区别,后面只是名字而已注意:动态参数必须在位置参数和默认参数的后面
-
*args
表示可以接收任意个参数,调用时,以元组的形式传递
def args_info(*args): print(args) print(type(args)) args_info(1, 2, 3) args_info([1, 2, 3]) ---------------------------------- (1, 2, 3) <class 'tuple'> ([1, 2, 3],) <class 'tuple'>
可见,无论是多个参数,还是一个参数,都会被打包成元组进行传递
那如果我们希望将一个列表,一个一个的传入,而不是整个列表一次性传入呢?
使用
*
对列表进行标记def args_info(*args): print(args) print(type(args)) args_info(*[1, 2, 3]) ---------------------------------- (1, 2, 3) <class 'tuple'>
-
**kwargs
表示可以接收任意个键值对参数,调用时,以字典的形式传递
def kwargs_info(**kwargs): print(kwargs) print(type(kwargs)) kwargs_info(name='python') kwargs_info(lis=[1, 2, 3]) kwargs_info(1, 2, 3) ---------------------------------- {'name': 'python'} <class 'dict'> {'lis': [1, 2, 3]} <class 'dict'> Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: kwargs_info() takes 0 positional arguments but 3 were given
同样和
*args
一样如果你想提供一个字典进行传参,可以直接在字典前面加上**
-
-
关键字参数
对与
*args
和**kwargs
方法我们可以传入任意的参数,这样的传入参数虽然灵活性很大,但是风险也很大,可控性差,必须要对自己需要的参数,进行过滤和判断。例如:我们只需要,年龄、姓名的性别,就需要自己写代码进行判断
def print_info(name, age, **kwargs): if 'sex' in kwargs: print(name + '-->' + str(age) + '--->' + kwargs['sex'])
这里我们可以使用
*
进行分隔def print_info(name, age, *, sex): pass print_info('剑魔', 20, sex='男')
这里要注意,如果已经有
*args
参数了,就不需要使用*
进行分隔了def print_info(name, age, *args, sex): pass print_info('剑魔', 20, sex='男')
return语句
return语句的意思就是函数到此为止,并且返回return后面表达式的结果。**一旦函数执行到return就会直接结束,无论return后面有多少内容都不会被执行,直接跳出函数体。**哪怕它在一个循环中。
return返回的可以是那些对象?
- 什么都不放回:
return
- 基本数据类型:
return 基本数据类型的值
- 表达式:
return 任意类型表达式
- 返回表达式的计算结果
- 函数:
return 函数
- 多个返回值:
return 值1, 值2, ....
如果你需要return可以返回任何python对象
return语句
return语句的意思就是函数到此为止,并且返回return后面表达式的结果。**一旦函数执行到return就会直接结束,无论return后面有多少内容都不会被执行,直接跳出函数体。**哪怕它在一个循环中。
return返回的可以是那些对象?
- 什么都不放回:
return
- 基本数据类型:
return 基本数据类型的值
- 表达式:
return 任意类型表达式
- 返回表达式的计算结果
- 函数:
return 函数
- 多个返回值:
return 值1, 值2, ....
如果你需要return可以返回任何python对象