函数
- 数学意义上的函数
- y = 2 x + 1 , y ∣ x = 3 = 2 × 3 + 1 = 7 y=2x+1,y|_{x=3}=2×3+1=7 y=2x+1,y∣x=3=2×3+1=7
- 编程意义上的函数
Python中函数的定义:函数是逻辑结构化和过程化的一种编程方法。
函数是可以重复使用的程序段。在开发程序时,需要某块代码多次,但是为了提高编写的效率以及代码的重用,所以把具有独立功能的代码块组织为一个小模块,这就是函数。
它们允许你给一块语句一个名称,然后你可以在你的程序的任何地方使用这个名称任意多次地运行这个语句块。这被称为调用函数
。我们已经使用了许多内建的函数,比如len()和range()。
函数定义和调用
函数定义
- 空函数
如果想定义一个什么事也不做的空函数,可以用pass语句:
def func():
pass
pass
语句什么都不做,那有什么用?实际上pass
可以用来作为占位符,比如现在还没想好怎么写函数的代码,就可以先放一个pass
,让代码能运行起来。
- 非空函数
函数通过def关键字定义,def关键字后跟一个函数的标识符,然后跟一对圆括号,圆括号之中可以包括一些变量名,该行以冒号结尾,接下来是一块语句,它们是函数体。
声明函数的一般形式如下:
def 函数名(参数列表)
'''说明'''
函数语句
return 返回值
说明如下:
1.函数代码块以def关键词开头,后接函数标识符名称和小括号()。
2.任何传入的参数和自变量必须放在圆括号中间,圆括号之间可以用于定义参数。
3.函数的第一行语句可以选择性地使用文档串----用于存放函数说明。
4.函数内容以冒号起始,并且缩进。
5.return[表达式]结束函数,选择性地返回一个值给调用方,不带表达式的return相当于返回None。
其中参数列表和返回值不是必须的,return也可以不跟返回值,甚至连return也没有。
对于return后没有返回值的和没有return语句的函数都会返回None值。
有些函数可能不需要传递参数,也没有返回值。
没有参数时,包含参数的圆括号也必须写上,圆括号后也必须有":"
现举一个简单的例子
def info():
"""打印信息"""
print({"name":"Tom","age":18})
info()
函数调用
函数定义后,我们就具备了实现某种功能的代码,执行这些代码,只需要调用函数。
函数调用形式:
info()
比如上面我们已经定义好了add()函数,现在我们调用:
# 定义函数
def info():
"""打印信息"""
print({"name":"Tom","age":18})
#调用函数
info()
现在整体写出代码:
#定义函数
def info():
"""打印信息"""
print({"name":"Tom","age":18})
#调用函数
info()
运行,结果为:
{'name': 'Tom', 'age': 18}
练习:定义函数实现调用函数能够输出姓名,年龄。
#利用传参的形式
def info(name,age):
print(name)
print(age)
info("lucy",7)
函数文档说明
在上面代码的基础上,添加
def info():
"""打印信息"""
print({"name":"Tom","age":18})
#调用函数
# info()
help(info)
运行后,结果为
Help on function info in module __main__:
info()
可以看到,help()返回add()函数的相关说明。
直接查看文档说明
print(info.__doc__)
#打印信息
函数参数
假如我们需要定义一个函数计算两个数的积,有人设计如下函数:
def mul():
x = 3
y = 3
print(x * y)
mul() # 9
这样可以吗?
这个函数只能实现3*3的结果,并不具备通用性。
为了让这个函数更具通用性,我们可以添加参数:
def mul(x, y):
print(x * y)
mul(3, 6) # 调用
- 参数调用的顺序
我们可以先看一下以下例子:
>>> def test(x,y):
... print(x)
... print(y)
...
>>> test(1,2)
1
2
>>> test(x=1,y=2)
1
2
>>> test(1,y=2)
1
2
>>> test(x=1,2)
File "<stdin>", line 1
SyntaxError: positional argument follows keyword argument
>>>
函数返回值
这里形象的解释一下函数:函数就是把一堆代码,打包放在那里,比如说一个发邮件的功能,然后这个功能被调用,说到这里大家应该会想知道,我们调了,但是调的一个结果是啥?有没有成功?如果成功,干A事情,如果不成功做B的事情。
返回值的定义:函数外部的代码要想获得函数的执行结果,就可以在函数里用return语句把结果返回。
函数参数种类
首先,了解两个概念:形参和实参
-
1)形参:
- 只有在被调用时才分配内存单元,在调用结束时,即刻释放所分配的内存单元,因此,形参只在函数内部有效,函数调用结束返回主调用函数后则不能再使用该形参变量;
-
2)实参:
- 实参可以是常量,变量,表达式,函数等,无论实参是何种类型的量,在进行函数调用的时候,他们都必须有确定的值,以便把这些值传给形参,因此应预先用赋值,输入等办法使参数获得确定值。
>>> def test(x,y):# test(x,y)指的是形参
... print(x)
... print(y)
...
>>> test(1,2)#1,2指的是实参
1
2
>>>
- 形参就是一把椅子,放在这里,占个位子而已,只到有人调用,赋值的时候才会分配内存单元,在调用结束,既可释放。
- 实参,就是实实在在存在,什么类型都接收。
1.位置参数
def usr_manager(name,age,job,hobby):
print("用户管理系统".center(16,'-'))
print("\tName:\t",name)
print("\tAge:\t",age)
print("\tJob:\t",job)
print("\tHobby:\t",hobby)
usr_manager("Tom",22,"IT","Read")
usr_manager("limei",23,"IT","Sing")
usr_manager("jim",21,"IT","Dance")
必须参数以正确的顺序传入函数,调用时的数量必须和声明时的一样。
2.默认值参数
假如我们设置hobby值为默认,即hobby=“Coding”.
def usr_manager(name,age,job,hobby="Coding")
print("用户管理系统".center(16,'-'))
print("\tName:\t",name)
print("\tAge:\t",age)
print("\tJob:\t",job)
print("\tHobby:\t",hobby)
print("用户管理系统".center(16,'-'))
usr_manager('lucy',21,'IT')#不传入参数,即为默认值
usr_manager('Tom',22,'IT','Read')#传入参数,则改变值
usr_manager('limei',23,'IT','Sing')#传入参数,则改变值
通过观察,可知:
如果定义默认参数,在调用的时候,不给实参,就会调用默认参数。
如果函数定义修改为:
>>> def usr_manager(name,age,job,hobby="Coding",job):
运行将报错:
def usr_manager(name,age,hobby="Coding",job):
print("\tName:\t",name)
print("\tAge:\t",age)
print("\tJob:\t",job)
print("\tHobby:\t",hobby)
usr_manager("Tom",22,"IT","Read")
usr_manager("limei",23,"IT","Sing")
usr_manager("jim",21,"IT","Dance")
#错误:SyntaxError: non-default argument follows default argument
因此,默认参数必须要放在位置参数的后边。
3.关键字参数
正常情况下,给函数传参数要按顺序,不想按顺序就可以用关键字参数,只需指定参数名即可(指定了参数名的参数就叫关键参数)
def usr_manager(name,age,hobby="Coding",job="IT"):
print("用户管理系统".center(16,'-'))
print("\tName:\t",name)
print("\tAge:\t",age)
print("\tJob:\t",job)
print("\tHobby:\t",hobby)
print("用户管理系统".center(16,'-'))
usr_manager("Tom",age=22,hobby="Read",job="IT")#传参时,关键字参数可以位置改变
usr_manager("limei",23,"IT","Sing")#不传关键字时,必须一一对应
以上代码运行结果:
-----用户管理系统-----
Name: Tom
Age: 22
Job: IT
Hobby: Read
-----用户管理系统-----
-----用户管理系统-----
Name: limei
Age: 23
Job: Sing
Hobby: IT
-----用户管理系统-----
关键参数必须放在位置参数(以位置顺序确定对应关系的参致)之后
4.不定参数
Python的不定参数,主要是指*args
和**kwargs
这两个魔法变量。那么它们到底是什么?
其实并不是必须写成*args
和**kwargs
。只有变量前面的 *
(星号)才是必须的。也可以写成*var
和**vars
。 而写成*args
和**kwargs
只是一个通俗的命名约定。
*args
和 **kwargs
主要用于函数定义。我们可以将不定数量的参数传递给一个函数。
这里的不定的意思是:预先并不知道, 函数使用者会传递多少个参数给你, 所以在这个场景下使用这两个关键字。
- *args` 的用法
*args
是用来发送一个非键值对的任意数量的可变数量的参数列表给一个函数。
下面我们举例来帮助大家理解:
def uncertain_para(para,*args):#传入一个参数只是将实参中的第一个值放在第一个形参中,其他的实参都给*args接收
print("普通参数:",para)
print("不定参数:",args)
print(type(args))
for arg in args:
print('逐一输出不定参数:',arg)
uncertain_para(1,2,3,4,5)
#以上代码运行的运行结果:
普通参数: 1
不定参数: (2, 3, 4, 5)
<class 'tuple'>
逐一输出不定参数: 2
逐一输出不定参数: 3
逐一输出不定参数: 4
逐一输出不定参数: 5
求平均值:
def test(para,*args):
print(type(test))
print(sum(args)/len(args))
print(test(1,2,3,4,5,6,7,8,9))
#结果:
<class 'function'>
5.5
None
**kwargs的用法
**kwargs允许我们将不定长度的键值对,作为参数传递给一个函数。
当我们想要在一个函数里处理带名字的参数时,就可以使用**kwargs.
比如:
def para(**kwargs):
print(type(kwargs))
print(kwargs)
para(a=3,b=4,c=5)
运行后输出:
<class 'dict'>
{'a': 3, 'b': 4, 'c': 5}
*args和**kwargs的使用
def test(para1,para2,para3):
print("para1:",para1)
print("para2:",para2)
print("para3:",para3)
args=("abc",6,9)
print(test(*args))
kwargs={"para1":3,"para2":"ws","para3":[1,2,3]}
print(test(**kwargs))
运行后输出:
para1: abc
para2: 6
para3: 9
None
para1: 3
para2: ws
para3: [1, 2, 3]
None
注意这里传递键值参数时,需满足参数数量一致,否则会报错。
标准参数与*args、**kwargs在使用时的顺序
那么如果你想在函数里同时使用所有这三个参数,顺序是这样的:
func(fargs,*args,**kwargs)
举例如下:
def test(para1,*para2,**para3):
print("para1:",para1)
print("para2:",para2)
print("para3:",para3)
print(test(1,2,3,4,a=5,b=6,c=7))
输出结果为:
para1: 1
para2: (2, 3, 4)
para3: {'a': 5, 'b': 6, 'c': 7}
None