Python函数复习
本章重点:
- 掌握函数参数传递
- 变量的作用域
- lambda函数
函数定义:
def functionname([ parameterlist]):
['''comments''']
[functionbody]
一、变量的作用域
作用域顾名思义是指变量能起作用的区域
- 局部变量:
函数内部的变量与函数外部的变量有着不同的储存地址不同的储存空间,函数内部的变量只在函数内部起作用不能在外部使用.当调用函数时候编译器才会给函数内部变量开辟内存空间,函数结束时内存自动释放.
- 全局变量:
在函数外部的变量叫做全局变量,或者在函数内部变量前加上global将局部变量变成全局变量,全局变量所有函数都能够使用.且如果函数内部的变量与外部变量有相同的变量名,由于储存空间和内存地址不同改变函数内部的变量不会改变函数外部的变量,除非将其变成全局变量
GlobalVariable = '一蓑烟雨任平生'
def function():
PartialVariable = '青山遮不住'
#试图在函数内部改变全局变量
GlobalVariable = '毕竟东流去'
print('局部变量PatialVariable:'+PartialVariable)
print('局部变量GlobalVariable:'+GlobalVariable)
function()
print('输出函数调用后的全局变量GlobalVariable:'+GlobalVariable)
print('试图输出局部变量PartialVariable:'+PartialVariable)
局部变量PatialVariable:青山遮不住
局部变量GlobalVariable:毕竟东流去
输出函数调用后的全局变量GlobalVariable:一蓑烟雨任平生
---------------------------------------------------------------------------
NameError Traceback (most recent call last)
<ipython-input-25-f6eb1ea5f97e> in <module>()
8 function()
9 print('输出函数调用后的全局变量GlobalVariable:'+GlobalVariable)
---> 10 print('试图输出局部变量PartialVariable:'+PartialVariable)
11
12
NameError: name 'PartialVariable' is not defined
很显然局部变量只在内部起作用且如果在函数内部有与全局变量同名的变量在函数内部改变不会影响到全局变量的数据
GlobalVariable = '一蓑烟雨任平生'
print('调用函数前的Globalvariable:'+GlobalVariable)
def function():
global PartialVariable
PartialVariable = '青山遮不住'
#在函数内部改变全局变量
global GlobalVariable
GlobalVariable = '毕竟东流去'
print('输出global PatialVariable:'+PartialVariable)
print('输出global GlobalVariable:'+GlobalVariable)
function()
print('函数外面输出函数调用后变量GlobalVariable:'+GlobalVariable)
print('函数外输出函数内变量PartialVariable:'+PartialVariable)
调用函数前的Globalvariable:一蓑烟雨任平生
输出global PatialVariable:青山遮不住
输出global GlobalVariable:毕竟东流去
函数外面输出函数调用后变量GlobalVariable:毕竟东流去
函数挖输出变量PartialVariable:青山遮不住
显然加了global即声明了把函数内部的变量变成了全局变量
二、函数参数传递:
- 了解形式参数和实际参数:
形式参数是定义函数时候函数名括号内的参数,而实际参数是在调用函数时的参数,函数的参数传递分为值传递和地址传递,所谓值传递就是在调用函数传参的时候将实际变量的值拷贝到形式参数里面,在函数内改变实际参数的值不会改变实际参数的值,而地址传递是指将实际参数的存储地址传递给形式参数,这时候因为形式参数和实际参数的引用指向同一个地址因此改变形式参数会影响得到实际参数的值,可变值类型是址传递,不可变类型是值传递.
- 位置参数:
1.传递参数时候在没有设置默认值的情况下必须保证实际参数个数与形式参数个数一致
2.传递参数时候位置必须与形式参数对应,否则会出现两种错误,抛出TypeError异常和产生结果与预期不一致
- 关键字参数:
关键字参数是指用形式参数name来输入参数值这时候可以以任何顺序输入参数
- 为参数设置默认值:
形式参数设置默认值了以后再调用函数传递参数的时候就可以省略掉设置了默认参数值的形式参数而不抛出异常
- 可变参数:
可变参数是指
- 返回值
函数中加入语句return
def function(string,num):
string = 'surprising'
num +=num
string = 'amazing'
nnum = [x for x in range(10)]
print('传递之前:','string='+string,'num=',num)
function(string,num)
print('传递之后:','string='+string,'num=',num)
传递之前: string=amazing num= [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
传递之后: string=amazing num= [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
数值类型和元组都是不可变类型,字典列表都是可变类型,上面的字符串类型是值传递,而可变列表是址传递
'''
位置参数:需要按照实际参数与形式参数顺序需一致
以计算某人的BMI指数为例子
'''
def function(person,weight,height):
BMI = weight/(height*height)
print(person+'的BMI指数为:'+str(BMI))
function('陆小凤',130,1.80)
陆小凤的BMI指数为:40.123456790123456
# 交换person和weight值出现TypeError错误
function(130,'陆小凤',1.80)
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
<ipython-input-3-ac6a152db519> in <module>()
1 # 交换person和weight值
----> 2 function(130,'陆小凤',1.80)
<ipython-input-2-c1ec9c54a6e6> in function(person, weight, height)
4 '''
5 def function(person,weight,height):
----> 6 BMI = weight/(height*height)
7 print(person+'的BMI指数为:'+str(BMI))
8 function('陆小凤',130,1.80)
TypeError: unsupported operand type(s) for /: 'str' and 'float'
# 交换weight和height顺序后计算结果与实际情况不一致
function('陆小凤',1.80,130)
陆小凤的BMI指数为:0.00010650887573964498
# 形式参数没有设置默认值时省略某个参数出错
function('陆小凤',130)
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
<ipython-input-5-18009db2c977> in <module>()
1 # 省略某个参数
----> 2 function('陆小凤',130)
TypeError: function() missing 1 required positional argument: 'height'
'''
关键字传参即用形式参数的参数名字传参的方式
这时候参数的顺序可以任意
'''
function(height=1.80,weight=130,person='陆小凤')
陆小凤的BMI指数为:40.123456790123456
'''
为参数设置默认值
'''
def defaultfun(a,b,c=1):
print(a+b+c)
defaultfun(a=1,b=1) #可省略c传参
3
'''
可变参数传参:
1.形式参数指定为*variable,这时候可将多个实际参数做成一个tuple传给形式参数
2.形式参数指定为**variable,这是将多个关键字传递的参数做成一个dict传给形式参数
'''
def MultiFun(*variable):
print('variable的类型为:',type(variable))
print('variable的总和为:',sum(variable))
MultiFun(1,2,3,4,5,6,7)
variable的类型为: <class 'tuple'>
variable的总和为: 28
def MultiFun(*variable,a=1,b):
print(variable,a,b)
MultiFun(1,2,3,4,5,a=4,b=2)
(1, 2, 3, 4, 5) 4 2
#可变参数不可用参数名传参
MultiFun(variable=1,a=2,b=4)
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
<ipython-input-19-5c9f755a3c78> in <module>()
1 #可变参数不可用参数名传参
----> 2 MultiFun(variable=1,a=2,b=4)
TypeError: MultiFun() got an unexpected keyword argument 'variable'
MultiFun(1,2,3)
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
<ipython-input-21-e48c708da2a5> in <module>()
----> 1 MultiFun(1,2,3)
TypeError: MultiFun() missing 1 required keyword-only argument: 'b'
#当*variable参数位于最前面时其他参数必须使用关键字参数传参
def MultiFun(*variable,a=1,b=1):
print(variable,a,b)
MultiFun(1,2,3)
MultiFun(1,a=2,b=2)
(1, 2, 3) 1 1
(1,) 2 2
def MultiFun(a=1,b,*variable):
print(variable,a,b)
MultiFun(a=1,b=2,3,4,5)
File "<ipython-input-26-8846f542c982>", line 1
def MultiFun(a=1,b,*variable):
^
SyntaxError: non-default argument follows default argument
上面出现语法错误说明关键字参数必须位于位置参数前面
#正确方式为
def MultiFun(a,b=1,*variable):
print(variable,a,b)
MultiFun(1,2,3)
(3,) 1 2
# 当所传参数是一个字典的时候需要用**variable
def dictfunction(**variable):
print(type(variable))
print(variable)
dictfunction(a=1,b=2,c=3)
<class 'dict'>
{'a': 1, 'b': 2, 'c': 3}
def dictfunction(**variable,a,b=1,*Variable):
print(variable,a,b)
dictfunction(c=1,a=2,b=3,2,2,3)
File "<ipython-input-37-77626ace6bff>", line 1
def dictfunction(**variable,a,b=1,*Variable):
^
SyntaxError: invalid syntax
idef dictfunction(a,b=1,*Variable,**variable):
print(a,b,Variable,variable)
dictfunction(1,2,3,2,2,3,c=4,d=4,f=4)
1 2 (3, 2, 2, 3) {'d': 4, 'f': 4, 'c': 4}
可变参数的字典形式必须位于最右端,列表形式的多变参数位于位置参数或者关键字参数之前时其他参数必须用关键字参数形式传参才会正确
# 将一个列表或者字典或者元组传递给一般参数
def function(variable1):
print(variable1)
list = [i for i in range(10)]
tuple = tuple(i+1 for i in range(10))
dict = {i:i+1 for i in range(10)}
function(list)
function(tuple)
function(dict)
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
{0: 1, 1: 2, 2: 3, 3: 4, 4: 5, 5: 6, 6: 7, 7: 8, 8: 9, 9: 10}
# 将一个列表、字典或者元组传递给可变参数
def function(*variable1):
print(variable1)
list = [i for i in range(10)]
tuple = tuple(i+1 for i in range(10))
dict = {i:i+1 for i in range(10)}
function(list)
([0, 1, 2, 3, 4, 5, 6, 7, 8, 9],)
function(tuple)
((1, 2, 3, 4, 5, 6, 7, 8, 9, 10),)
function(dict)
({0: 1, 1: 2, 2: 3, 3: 4, 4: 5, 5: 6, 6: 7, 7: 8, 8: 9, 9: 10},)
function(*list)
function(*tuple)
(0, 1, 2, 3, 4, 5, 6, 7, 8, 9)
(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
#字典键打包作成元组
function(*dict)
(0, 1, 2, 3, 4, 5, 6, 7, 8, 9)
从上面例子可以看出当把一个list,tuple,dict的实际参数传递给可变参数variable的时候是将list,tuple,dict(其键)当做一个整体打包作成一个元组,而要想只取出list,tuple,dict中的值就需要解包即list、tuple、dict
# 将字典中的键值对传递给可变参数**variable作成一个字典时候也需要解包**dict
import random
def function(**variable1):
print(variable1)
dict = {i:random.randint(10,100) for i in range(10)}
function(dict)
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
<ipython-input-50-bb64e41d0e07> in <module>()
4 print(variable1)
5 dict = {i:random.randint(10,100) for i in range(10)}
----> 6 function(dict)
TypeError: function() takes 0 positional arguments but 1 was given
可以看到直接传参会出错
# 正确方式
import random
def function(**variable):
print(variable)
dict = {i:random.randint(10,100) for i in range(10)}
function(**dict)
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
<ipython-input-56-fc076f460804> in <module>()
4 print(variable)
5 dict = {i:random.randint(10,100) for i in range(10)}
----> 6 function(**dict)
TypeError: function() keywords must be strings
可以看到上面出错TypeError: function() keywords must be strings,提示出错原因键必须是字符串类型
import random
def function(**variable):
print(variable)
dict = {'数学':150,'英语':70}
print(dict)
function(**dict)
{'英语': 70, '数学': 150}
{'英语': 70, '数学': 150}
将一个字典传递给可变参数时候那个dict.keys必须是string内心才可以
# 函数中return函数的使用
def function(a,b):
return a+b
dict1 = {'c':1,'d':2} #字典的键与形式参数不一致
dict2 = {'b':1,'a':2} #子弹的键与形式参数一致
c = function(**dict2)
print(c)
d = function(**dict1)
print(d)
3
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
<ipython-input-85-c8ea739e8870> in <module>()
6 c = function(**dict2)
7 print(c)
----> 8 d = function(**dict1)
9 print(d)
TypeError: function() got an unexpected keyword argument 'd'
由上面的例子可以看出在传递参数时解包字典dict={'a':1,'b':c}实际上是将键值对转化成了等式a=1,b=2在传递参数的时候就相当于是传递了a=1,b=2两个参数即function(dict)=function(a=1,b=2)因此字典键值不能是数字型必须是字符串形式不然会出错,而且当形式参数是function(variable1,variable2)时候其variable1、variable2也要与dict的键名相同才可以.
#如下可见*dict其实是提取出dict的键
dict = {'a':1,'b':2}
print(*dict)
a b
# lambda表达式的使用
bookinfo = [('人类简史',68,100),('中国通史',68,120),('机器学习',48,100)]
bookinfo.sort(key=lambda x:(x[1],x[1]/x[2]))
print(bookinfo)
[('机器学习', 48, 100), ('中国通史', 68, 120), ('人类简史', 68, 100)]
key = lambda x:(x[1],x[1]/x[2])是指定列表的排序方式为优先每个元素的第二个位置的值的大小按升序排列,其次按第一个元素除上第二个元素升序排列
lambda variable1.....:expression
variable1.....表示要传递的参数,expression表示表达式,lambda函数能够返回一个值必须要将返回值赋值给变量,一般这样的匿名函数用于需要几句话处理且一次性使用的功能.