def Test(*args): #关于动态传参
print(args) #打印:(1, 2, 3, 4, 5)
print(*args) #打印:1 2 3 4 5 这个就是五个数,
print(type(args)) #打印<class 'tuple'>
#你可能会疑问,为什么有时候打印是以元组的形式,有时候打印是五个散的数,
#函数头的*代表聚合,函数里面的*代表打散,
Test(1,2,3,4,5)
def func(a,b,c,d,*args,e='男'): #位置参数,动态传参,默认参数mixed的情况,!!!这样写是对的,
print(a)
print(b)
print(c)
print(d)
print(args)
print(e)
func(1,2,3,4,5,6,7,e='女')
#你若是把函数定义中e='男'放到*args前面,就会报错:TypeError: func() got multiple values for argument 'e'
#**kwargs 动态传参,他将所有的关键字参数(无意义的)放到一个字典中,这个无意义形容的很到位!!!!
def func(a,b,c,**kwargs):
print(kwargs)
func(1,2,r=4,b1=5,c1=6,c=7,)
#打印:{'c1': 6, 'r': 4, 'b1': 5}
#来说说为什么这么打印,
#1给了位置参数a,2给了位置参数b,
#c是关键字传参,可以不用紧挨着给值,
#后面的关键字形式的传参,都收进了**kwargs里面了,以字典的形式存储了,
def sun(a,b,c,**kwargs,*args):
pass
#报错:*parameter after **parameter,所以这种形式就不允许,
def func(a,b,c,d,*args,e='男',**kwargs):
print(a)
print(b)
print(c)
print(d)
print(args)
print(e)
print(kwargs)
func(1,2,3,4,5,6,7,v=3,m=7,h=9,e='女')
# 最终顺序:位置参数,*args,默认参数,**kwargs
#我再来解读以下,
#首先是前面放位置参数,没毛病,
#其次上面才说,默认参数不能放在*args前面,
#*args不能放在**kwargs后面,
#默认参数,也不能放**kwargs之后,
#so,最终形式,就是
#def func(a,b,c,d,*args,e='男',**kwargs):
来个小故事,
面试的时候,20来岁的面试官,你表现的不要太NB;40来岁的,你尽力表现。
l1 = [1,2,30]
l2 = [1,2,33,21,45,66]
def fun(*args):
print(args)
fun(*l1,*l2)
#打印结果:
#(1, 2, 30, 1, 2, 33, 21, 45, 66),直接就把两个列表合在一起了,
#上面和下面两段程序,功能一样,不同的是,一个是元组,一个是字典,
#简单说,一个聚合的是许多单个元素,一个聚合的是许多“键值对”形式的元素
def func(**kwargs):
print(kwargs)
dic1 = {'name1':'ZS','age1':46}
dic2 = {'name':'LS','age':56}
func(**dic1,**dic2)
#打印结果
#{'age1': 46, 'name1': 'ZS', 'age': 56, 'name': 'LS'}
def func(*args):
print(args)
func(*{'name':'alex',"age":12})
#打印结果,这个字典的特殊,注意看,
#('name', 'age')
# 在函数的调用执行时,
# *可迭代对象,代表打散(list,tuple,str,dict(键))将元素一一添加到args。
# **字典,代表打散,将所有键值对放到一个kwargs字典里。
# 我自己补充一点!!!字典我们很容易想到键值对,但若仅仅传入字典变量的名字,就会被当作单个元素的变量看待,
def func(**kwargs):
print(kwargs)
dic1 = {'name1':'alex','age1':46}
dic2 = {'name':'老男孩','age':56}
func(**dic1,**dic2) #打印结果:{'age1': 46, 'age': 56, 'name1': 'alex', 'name': '老男孩'}
#上面这个版本的程序,是原版,
#因为这个是字典,比较特殊,
#我特地改为了下面这种形式,
def func(*args):
print(args)
dic1 = {'name1':'alex','age1':46}
dic2 = {'name':'老男孩','age':56}
func(*dic1,*dic2) #打印结果:('age1', 'name1', 'age', 'name')
# 在函数定义时, *args,**kwargs代表的是聚合。
def func(*args,**kwargs):
print(args)
print(kwargs) #打印结果:{'age1': 46, 'age': 56, 'name1': 'alex', 'name': '老男孩'}
print(*kwargs) #打印结果:age1 age name1 name
# print(**kwargs) #这个形式,是错的,根本就没这个写法,*的写法在函数内,无*的代表聚合状态,有*的代表打散状态,
dic1 = {'name1':'alex','age1':46}
dic2 = {'name':'老男孩','age':56}
func(*[1,2,3,4],*'asdfsad',**dic1,**dic2)
#这个是一个综合的例子,
#所有的一个*的归入args,所有的两个*的归入kwargs
动态传参在此结束,
名称空间,临时名称空间,没什么好写的,pass,
a = 2
b = 3
def func1():
c = 5
d = 6
print(globals()) # 关于全局的一些信息,可以不看
return locals() # 打印结果:{'c': 5, 'd': 6},就是函数内部变量的信息,
print(func1())
print(globals()) # 全局名称空间:所有变量
print(locals()) # 局部名称空间:所有变量
#1,在局部空间内,声明一个全局变量
def func1():
global name #这是主角
name = '老男孩'
print(name)
func1()
print(name)
#如果仅仅是局部变量,函数结束后就无法使用了,
#但是在函数内部,由于使用了global,这个函数内声明的name,升级为全局的了。
# 2,在局部空间内改变一个全局变量
a = 4
def func1():
global a #在局部空间内,使用全局变量,非列表元组等,要加global声明,
a = 5
# print(name)
func1()
print(a) #打印结果5,说明在函数内部,成功更改了全局变量a的值(原本是4)
#nonlocal
# 1,不能修改全局变量。
# a = 4
# def func1():
# nonlocal a
# a = 5
# # print(name)
# func1()
# print(a)
#会报错:SyntaxError: no binding for nonlocal 'a' found
#nonlocal是针对,更内部局部对靠外的局部的引用,
#而这里引用的范围错了,引用到了全局了,所以报错!!!
#在局部作用域中,对父级作用域(或者更外层作用域非全局作用域)的变量进行引用和修改,
# 并且引用的哪层,从那层及以下此变量全部发生改变。
# a = 4
# def func1():
# b = 6
# def func2():
# b = 666
# print(b) #666
# func2()
# print(b) # 6
# func1()
#打印结果,没什么好说,pass!!!
#666,6
b = 4
def func1():
#global b #这句取消注释,就会报错,
b = 6
def func2():
nonlocal b
b = 666
print(b) #
func2()
print(b) #
print(b)
func1()
#报错信息:SyntaxError: no binding for nonlocal 'b' found
#在func1()内global b之后,b就是全局的了,
#而后面func2()内,又使用nonlocal进行内部引用,注意!!!这个引用是针对非全局变量的,
#so,
#明显这两个引用就是相互矛盾的,
#注释掉global b之后,
#打印结果是:
# 4
# 666
# 666