今日内容大纲
1.动态参数 *args,**kwargs
2.名称空间,作用域,作用域链,加载顺序等
3.函数的嵌套
4.global,nonlocal
1.动态参数
'''
用户传入到函数中的实参数量不定时,或者是为了以后拓展,
此时要用到动态参数*args,**kwargs(万能参数。)
*args接收的是所有的位置参数。
**kwargs接收的是所有的关键字参数。
顺序:位置参数,*args,默认参数, **kwargs
'''
例1:*args接收的是所有的位置参数。
**kwargs接收的是所有的关键字参数。
def func(*args,**kwargs):
print(args)
print(kwargs)
func(11, 22, 33, name = "david", age = 100)
执行结果:顺序:位置参数,*args,默认参数, **kwargs
(11, 22, 33)
{'name': 'david', 'age': 100}
例2:
def func(a, b, *args, sex = "男",**kwargs): #若sex = "男",在 *args之前,则33会覆盖"男"
print(a,b)
print(args)
print(sex)
print(kwargs)
func(11, 22, 33, 44, 55, name = "david", age = 100)
执行结果:
def func(a, b, *args, sex = "男",**kwargs):
print(a,b)
print(args)
print(sex)
print(kwargs)
func(11, 22, 33, 44, 55, name = "david", age = 100)
def func(a, b, *args, sex = "男",**kwargs):
print(a,b)
print(args)
print(sex)
print(kwargs)
func(11, 22, 33, 44, 55, sex="女",name="david",age=100) #关键字参数 sex="女",只要在位置参数之后即可,形参中会找到sex覆盖"男"
例3:多个数的相加
def sum1(*args):
sum = 0
for i in args:
if type(i) == int:
sum += i
return sum
print(sum1(1,2,3,4,"af"))
例4:将两个列表用*args传参,最后打印args合并成一个
方法一:
def func1(*args):
li = []
for i in args:
li.extend(i)
print(tuple(li))
l1 = [11, 22, 33]
l2 = [44, 55, 66]
func1(l1,l2)
方法二:
def func1(*args): #聚合一个个位置参数形成元组(11, 22, 33, 44, 55, 66)
print(args)
l1 = [11, 22, 33]
l2 = [44, 55, 66]
func1(*l1,*l2) #打碎l1,形成一个个位置参数 11,22,33 打碎l2 得到 44,55, 66
2.名称空间,作用域,作用域链,加载顺序
(1) '''
当程序运行时,代码从上至下一次读取,遇到变量与值,
他会在内存中开辟一个空间,存放变量与值的内存地址的对应关系。
这样存储变量与值得对应关系的空间叫做名称空间(命名空间)。
当解释器遇到函数时,他会将函数名存储在内存中,但是对于函数体莫不关心。
当函数执行时,他会通过函数名找到函数体,然后将函数体里面的变量等对应关系存放在一个
临时开辟的空间中,随着函数的结束,临时的空间关闭,这样的空间叫做临时名称空间。
'''
name = "alex"
def func1():
name = "david"
print(name)
func1()
print(name)
(2)'''
内置名称空间:打开解释器,解释器加载到内存,同时会在内存中加载内置名称空间,即内置函数存放的空间
len() print() input() list
list
name
print(666)
'''
(3)'''
名称空间:
内置名称空间:内存中内置函数存放的空间
全局名称空间:内存中全局变量与值的内存地址的对应关系存放的空间
局部名称空间:函数中变量与值的内存地址的对应关系存放的临时空间
内存加载顺序:内置名称空间 ---> 全局名称空间(程序运行时) ---->局部名称空间(函数执行时)
作用域:
全局作用域:内置名称空间 全局名称空间
局部作用域:局部名称空间
取值顺序(单项):局部名称空间(函数执行时) ---> 全局名称空间 ---> 内置名称空间
L local
E eclose
G global
B Built-in
'''
例1:
sum = 666 # global
def func1():
sum = 555 # eclose
print(sum)
def inner():
pass
sum = 111 # local
# print(sum)
inner()
func1()
例2:
sum = 666
def func1():
sum = 555
print(sum)
func1()
print(sum)
执行结果:
555 666
3.函数的嵌套
例1:
print(111) # 1
def func1():
name = 'alex'
print(name) # 2
def inner():
a = 2
print(a) # 3
inner()
func1()
执行结果:
111 alex 2
例2:
print(111)
def func1():
name = 'alex'
print(name)
def inner():
a = 2
print(a)
inner()
print(333)
func1()
print(444)
执行结果:
111 333 alex 2
例3:
print(111)
def func1():
name = 'alex'
print(name)
def inner():
a = 2
print(a)
print(444)
inner()
print(555)
func1()
执行结果:
111 alex 444 2 555
例4:
def func1():
a = 666
print(666)
def func2():
name = 'taibai'
print(name)
func1()
print(333)
func2()
print(555)
执行结果:
333 taibai 666 555
4.global,nonlocal
(1)global
1)在全局变量不存在时,要想使用函数中的局部变量
方法一:将函数中的局部变量作为返回值,赋值给全局作用域中的变量
def func1():
name = 'alex'
return name
ret = func1()
print(ret)
方法二:在函数局部作用域中,通过global声明一个全局变量
def func1():
global name
name = 'alex'
func1()
print(name)# 打印 声明过的全局变量"alex"
2)若全局变量不可变类型,要想在局部作用域中修改全局变量,直接修改不会改变全局变量的值,需要先声明全局变量,再做修改
name = '老男孩'
def func1():
global name
name = 'alex'
func1()
print(name) #打印修改后的全局变量 "alex"
3)若全局变量是可变类型,在局部作用域中,无需用global声明,直接修改即可
对于可变的数据类型,函数中如果对其进行操作,改变全局不用引用global.
l1 = [1, 2, 3]
def func1():
l1.append(666)
func1()
print(l1) #打印结果:[1, 2, 3, 666]
(2)nonlocal
1)不能改变一个全局变量.
name = "老男孩"
def func1():
nonlocal name
print(name)
func1()
报错:不能使用或者改变全局变量
2)在局部作用域中,对父级作用域(或者更外层作用域非全局作用域)的变量进行引用和修改,
并且引用的哪层,从那层及以下此变量全部发生改变。
例1:
def func1():
name = 'alex'
print(name) # 1, alex
def inner():
nonlocal name #对父级作用域的变量进行引用
name = '老男孩' #对变量做修改
print(name) # 2 老男孩
inner()
print(name) # 3,alex 老男孩 #修改后的那层及以下此变量全部发生改变
func1()
执行结果:
alex 老男孩 老男孩
例2:
def add_b():
b = 42
def do_global():
b = 10
print(b) #1
def dd_nonlocal():
nonlocal b
b = b + 20
print(b) #2
dd_nonlocal()
print(b) #3
do_global()
print(b) #4
add_b()
执行结果:
10 30 30 42