---恢复内容开始---
一、可变长参数:
指的是在函数调用时,传入的参数不固定
四种可变长参数:可变长形参 * ,可变长实参 * ,可变长形参**,可变长实参**
1.可变长形参之 * :形参中*会将溢出的位置实参全部接收,,然后存储成元祖的形式,再把元祖赋值到给*后面的参数。约定为*args
def fun1(a,*args):
print(a , args)
fun1(1,2)
fun1(1,2,3)
打印结果为:1(2,)
1(2,3)
2.可变长实参之 * :实参中的*,会将*后面的参数循环取出来,打散成位置实参,,以后但凡看到实参前面带*,就看成是位置实参,马上打散成位置实参去看。
def fun1(a,b,c,d,*args):
print(a,b,c,d,args)
fun1(1,*(2,3,4),5,6)
打印结果为:1 2 3 4(5,6)
3.可变长形参之 ** :形参中的**,会将溢出的关键字实参全部接收,然后存储成字典的形式,再赋值给**后的参数,约定为**kwargs
def fun1(a,**kwargs):
print(a , kwargs)
fun1(1,b=2,c=3)
打印结果为:1{'b'=2,'c'=3}
4.可变长实参**:实参中的**,会将**后面的参数循环取出来,打散成关键字实参,以后但凡看到实参前带**,就是把它看成关键字实参,马上打散成关键字实参去看。
def fun1(x,y,**kwargs):
print(x,y,kwargs)
fun1(1,2,**{'a':1,'b':2})
打印结果为:1 2 {'a': 1, 'b': 2}
5.可变长参数应用:
def index(name,age,sex): print(f'name:{name},age:{age},sex:{sex}') def wrapper(*args,**kwargs): print(f'args:{args}') print(f'kwargs:{kwargs}') index(*args,**kwargs) wrapper(name='nick',age=19,sex='male')
打印结果为: args:() # *arges只接受溢出的位置实参,但wrapper没有传入位置实参,为空元祖
kwargs:{'name': 'nick', 'age': 19, 'sex': 'male'}接收所有溢出关键字实参
name:nick,age:19,sex:male
二、函数对象
函数是第一类对象,可以被当作数据处理
函数的四大功能:
1.引用
def func(): print('from func') print(func) f = func #换了个名字,内存地址两者一样 print(f)
运行结果为:
<function func at 0x000001D3653E40D0>
<function func at 0x000001D3653E40D0>
2.当作函数传给一个函数
def func():
print('from func')
def foo(m):
m()
foo(func) #函数名称可以被当作参数来传递
打印结果为:from func
3.当作函数返回值
def func():
print('from func')
def foo(m):
return m
res = foo(func) #此时func被当作返回值,虽然它是一个函数
print(res)
res()
打印结果为:
<function func at 0x000001D3653E60D0>
from func
4.可以当作容器类型的元素
def func():
print('from func')
l = [func] #放入到列表容器中
l[0]()
打印结果为:
from func
三、函数的嵌套
函数内部再定义函数,此时函数外部无法使用内部定义的函数
def f1():
def f2():
print('from f2')
f2()
f2()
此时报错:NameError: name 'f2' is not defined
def f1():
def f2():
print('from f2')
f2()
f1()
打印结果为: from f2
找出4个数的最大值:
def max2(x,y): if x>y: return x else: return y def max4(a,b,c,d): res1 = max2(a,b) res2 = max2(c,d) res3 = max2(res1,res2) print(res3) max4(1,2,3,4)
打印结果为:4
四、函数名称和作用域
名称空间:内存中存储的变量名誉变量间绑定关系的空间
1.内置名称空间 :存储python解释器自带的名字,解释器启动时生效,关闭无效,如 int,float,len
2.全局名称空间:除了内置和局部都叫全局,文件执行时生效,文件执行结束失效。
x = 1
def fun():
pass
1 = [1,2]
if 3>2:
if 4>3:
z = 3
# x,fun,l,z都是全局名称空间
3.局部名称空间:存放函数调用时产生的名字
def f1():
def f2():
print('from f2')
f2()
f1()
# f2是局部名称空间
4.加载顺序:.py文件由python解释器打开,因此,内置名称空间先加载,结束后文件才打开,此时产生全局名称空间,只有当函数被调用时,才会产生局部名称空间,因此名称空间加载顺序为: 内置---》全局----》局部
5.查找顺序: 先从当前位置查找,找不到就按照这种顺序查找-----局部>>全局>>内置,不逆向查找
len = 10
def f1():
len = 20
print(len)
f1()
打印结果为:20 从局部开始查找,找到len = 20
作用域:作用的区域
1.全局作用域:全局有效,全局存活,包括内置名称空间和全局名称空间。
2.局部作用域:局部有效,临时存储,只包含局部名产空间。
注意:作用域关系在函数定义阶段就固定死了,与函数调用无关
x = 1
def f1():
print(x)
def f2():
x = 2
f1()
f2()
打印结果为:1
global 和 nonlocal 关键字打破规则
x = 1 def f1(): x = 2 def f2(): global x #把局部变量修改为全局变量 x = 3 f2() print(x) f1() print(x)
打印结果为:3
x = 1 def f1(): x = 2 def f2(): nonlocal x #修改上一个局部变量为3 x = 3 f2() print(x) f1() print(x,x)
打印结果为:3
(1,1)
注意点:
1.在局部想要修改全局的可变类型,不需要任何声明,可以直接修改 如在函数中添加全局的列表的值
2.在局部如果想修改全局的不可变类型,需要借助global来声明为全局变量,即可直接修改