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