文章目录
前言
函数是学习Python正式的开始,我们来探索函数的奥秘吧。
一、函数入门
函数是执行特定任务的一段代码,通过将一段代码定义为函数,并为其命名,可以在需要的时候多次调用该段代码,节省了时间成本,也让程序更加简洁。
1.1、定义函数
def 函数名(形参列表):
//由0到多条可执行语句组成的函数
[return [返回值]]
1.2 返回值
程序通过return返回函数的结果,如果有多个返回值,可以将多个值包装成列表之后返回,也可以直接返回,这个时候,Python会自动将这多个返回值封装成元组。当然,我们也可以通过之前提到的序列解包,直接用多个变量接收多个返回值
二、函数的参数
1.关键字参数
按照形参的位置传入的参数被称为位置参数,如果使用位置参数传参,必须按照定义时的参数顺序,如果按照参数名传参,则不必按照定义形参的顺序传入。这种方式就叫关键字参数。
2、参数默认值
在定义函数时给参数赋值,所赋值为函数参数的默认值,若不重新赋值则使用默认值。
在给参数重新赋值时,可以通过位置参数赋值,也可按照参数名赋值,如下?
def say_hi(name = 'csdn',message = 'hello'):
print(name,',你好')
print('消息是',message)
say_hi() # 此时name=csdn,message=hello
say_hi('任嘉伦') # 此时name='任嘉伦',message='hello'
say_hi('任嘉伦','好帅') #此时name='任嘉伦',message='好帅'
say_hi(name = '任嘉伦',message = '好帅') #此时name='任嘉伦',message='好帅'
say_hi(message = '好帅',name = '任嘉伦') #此时name='任嘉伦',message='好帅'
需注意的是,按照位置参数赋值必须按照参数顺序进行赋值,通过参数名赋值则与顺序无关,但是,关键字参数必须在位置参数后,调用函数时,若传入的第一个参数不指定参数名,默认是第一个参数的值,后面再进行参数名赋值的时候,只能使用第二个参数名及以后的参数名。若文字有些晦涩难懂,可以举个栗子
say_hi('csdn',name='任嘉伦')
# 报错原因,默认csdn是赋值给name的,但是又使用参数名赋值方式再次赋值了name
say_hi(name='任嘉伦','csdn',)
# 报错原因,已经使用参数名赋值方式给name赋值,但是'csdn'位置参数默认赋值给name进行了再次赋值
而正确的赋值是下面的代码
say_hi('csdn',message = 'hello')
say_hi(name= 'csdn',message = 'hello')
我们可以说,位置参数的赋值是有自己的规则的,从左往右第一个位置参数就是给第一个参数名的,因此不能再使用参数名赋值方式对第一个参数名重新赋值。
3、参数收集(个数可变的参数)
我们在前面的序列封包和序列解包部分,介绍过使用*接收列表的栗子,此处接收个数可变的参数值也是通过它实现的。我们看下面的栗子
def test(a,*stars):
print(stars)
for i in stars:
print(i)
print(a)
test(3,"迪丽热巴","任嘉伦","阿纪")
'''
输出结果:
("迪丽热巴","任嘉伦","阿纪")
迪丽热巴
任嘉伦
阿纪
3
'''
?Python允许个数可变的形参可以处于参数列表的任意位置,但是一个函数最多只能带一个支持“普通”参数收集的形参,它会以元组形式存在。
参数列表中个数可变的形参后只能只用关键字参数,否则程序会把所传入的多个值都当成是给个数可变的形参的。
Python 在参数前加两个*,还可以收集关键字参数,它会以字典形式存在。这样一个函数可以同事包含一个支持“普通”参数收集的参数和一个支持关键字参数收集的参数。
def test(x,y,z=5,*stars,**name):
print(x,y,z)
print(stars)
print(name)
test(1,2,3,"任嘉伦","迪丽热巴","郭晓婷",任嘉伦=001,迪丽热巴=002,郭晓婷=003)
'''
输出结果
1,2,5
("任嘉伦","迪丽热巴","郭晓婷")
{'任嘉伦':001,'迪丽热巴':002,'郭晓婷':003}
'''
4、逆向参数收集
逆向参数收集是指,在程序已有列表,元组,字典等对象前提下,把他们的元素拆开后传递给函数的参数。
逆向参数需要在函数调用时,传入的列表,元组参数前加一个星号,字典参数前加两个星号。
def test(a,*name):
print(x,y,z)
print(stars)
print(name)
a_tuple = ("任嘉伦","迪丽热巴","郭晓婷")
test(*a_tuple) # 此时a="任嘉伦",name=("迪丽热巴","郭晓婷")
# 不用逆向收集,参数全部传递给了a
def test(a,*name):
print(x,y,z)
print(stars)
print(name)
a_tuple = ("任嘉伦","迪丽热巴","郭晓婷")
test(a_tuple) # 此时,a=("任嘉伦","迪丽热巴","郭晓婷"),name=()
同理,字典参数前加两个星号,,即可通过键使用值
5、函数的参数传递机制
Python中的参数传递机制都是值传递,就是说,传进函数里的是实际参数值的复制品,因此,如果在函数里对传递的参数做任何更改的操作都不会改变原来的参数本身值。
如果想让函数修改某些变量,则可以通过把这些数据包装成列表,字典的等可变对象,然后把列表,字典等可变对象通过参数传入函数,在函数中通过列表,字典的方法修改它们。
6、变量作用域
变量是有自己的作用域的,根据定义变量的位置可以分为两种:
? ? ? ? (1)全局变量:在函数外,全局范围内定义的变量,可以在所有函数内都可被访问
? ? ? ? (2)局部变量:在函数中定义的变量,包括参数。
三个函数:
(1)globals()返回全局范围内所有变量组成的字典,可以在任何函数内使用均有相同效果
(2)locals()返回当前局部范围内所有变量组成的字典,在函数外调用此函数时,和globals()有一样的效果
(3)vars(object)获取在指定对象范围内所有变量组成的字典,若不传入object则其和locals的作用相同
不管是使用globals()
还是使用
locals()
?
获取的全局范围内的“变量字典’ 都可以
被修改,而这种修改会真正改变全局变量本身:但通过
locals()
?
获取的局部范围内的“变量
字典”,即使对它修改也不会影响局部变量。
三、函数的高级部分
1、局部函数
变量有全局变量和局部变量,其实函数也有全局函数和局部函数,我们之前学到的都是全局函数,局部函数是定义在函数体内的函数,默认是对外隐藏的,局部函数只能在封闭函数内有效,封闭函数可以返回局部函数,以便在其他函数内使用。
def get_math(type,n):
def square(n):
return n*n
def cube(n):
return n*n*n
if type == "square":
return square(n)
elif type == "cube":
return cube(n)
else:
print("输入错误")
print(get_math("square",3)) # 输出9
pirnt(get_math("cube",2)) # 输出8
需要注意的是,局部函数内的变量也会遮蔽它所在函数的局部变量,举个栗子:
def func():
name = "Tom" # 局部函数所在函数的局部变量
def test(): # 局部函数
print(name) # =Tom
name = 'Mary' # 遮蔽了局部函数所在函数的局部变量
test()
func()
上面的代码会报错,因为局部变量遮蔽了局部变量
那么如何解决这个问题呢?通过nonlocal关键字
def func():
name = "Tom" # 局部函数所在函数的局部变量
def test(): # 局部函数
nonlocal name # 此处通过nonlocal声明局部函数可以访问其所在函数的变量
print(name) # =Tom
name = 'Mary' # 遮蔽了局部函数所在函数的局部变量
print(name) # =Mary
test()
func()
如果封闭函数将局部函数返回,且程序使用变量保存了封闭函数的返回值,那么这些局部函数的作用域就会变大,就像是全局函数一样
def get_math(type,n):
def square(n):
return n*n
def cube(n):
return n*n*n
if type == "square":
return square(n)
elif type == "cube":
return cube(n)
else:
print("输入错误")
print('--------------------------------------------')
# 我们注意到,上面的函数就是在介绍局部函数时用到的,那么接下来介绍新的用法
math_func=get_math("square")
print(math_func(3)) # 9
math_func=get_math("cube")
print(math_func(2)) # 8
2、使用函数变量
所有的函数都是function对象,这意味着可以把函数本身赋值给变量,这样程序也可以通过变量来调用函数,其实就像函数有了第二个名字。
3、使用函数作为函数形参
通过传入函数形参,我们能够动态改变程序的某些代码,这用于处理某些暂时无法确定的逻辑。
四、lambda表达式
语法:lambda [parameter_list] : 表达式
lambda关键字后,冒号左面是参数列表,可以没有,可以有多个,冒号右面是表达式的返回值。
lambda表达式只能创建简单函数对象,更适合函数体为单行的情形,函数比lambda表达式的适用性更强。
总结
以上就是今天要讲的内容,本文简单介绍了函数的应用,希望大家都能掌握。
|