# 函数的命名空和作用域
#命名空间 有三种
# 内置命名空间 --- python解释器
# 就是python解释器,一启动就可以使用的名字存储在内置命名空间中
# 如print(),input()等等....
# 内置的名字在启动解释器的时候被加载进内存中
# 全局命名空间 --- 编写的代码,但不是定义函数中的代码
# 是在程序从上到下被执行的过程中依次加载进内存的
# 放置了我们设置的所有变量名和函数名
# 局部命名空间 --- 函数
# 就是函数内部定义的名字
# 当调用函数的时候,才会产生这个名称空间,随着函数执行的结束,这个命名空间就消失了
# 在局部:可以使用全区、内置命名空间中的名字
# 在全局:可以使用内置命名空间的名字,但是不能使用局部中的名字
# a = 1 # def test():
# def test(): # a=1
# print(a) # print(a)
# # test()
# test() # print(a)
# 在内置:不可以使用全局和局部命名空间的名字:因为它在解释器启动的时候已经开始使用,不依赖用户编写的代码进行启动。
# 依赖倒置原则:内置命名空间A包含全局命名空间B,全局命名空间B里包含局部命名空间C;
# 即:A>B>C,A为底层,B为中间层,C为上层,c可以从A,B取值,B能取A的值取不了C的值,A取不了BC的值
# 在正常情况下,直接使用内置的名字
# 当我们在全局定义了和内置名字空间中同名的时候,会使用全局的名字
# 当本身有的时候,就不找上级的要。
# 如果自己没有,就向上级要
# 如果自己没有,就找上级要,上级没有再找上级,如果内置命名空间没有,就报错
# 多个函数应该拥有多个独立的局部命名空间,且互不关联
# def max():
# print(" in max now")
#
# print(max())
#进Debug模式查看运行顺序
# def input():
# print('in input now')
#
# def test():
# input()
#
# test()
# 作用域
#只有两种
#全局作用域 --- 作用在全局 --- 内置和全局名字空间中的名字都属于作用域---globals(),查看全局域中有什么名字,仅查看,无论放哪里,都时查看全局的。
#局部作用域 --- 作用在局部 --- 函数(局部名字空间中的名字属于局部作用域)---locals(),查看作用域中有什么名字,仅查看,如果放在全局,则查看全局的。
# 对于不可变数据变类型,在局部中是可以查看全局作用域中的变量
# 但是不能直接修改
a = 1
def test():
a =2
return a
a = test()
print(a)
# 如果需要修改,需要函数开始时进行global声明
#如果在一个局部函数内生命了一个global变量,那么这个变量在局部的所有操作将对全局的变量有效
# a = 1
# def test():
# global a
# a += 1
# 函数的嵌套定义
#内部函数可以使用外部函数的定义
# def test():
# a = 1
# def other():
# b =2
# print(a)
# print('other')
# def other1():
# print(a,b)
# print('other1')
# other1()
# other()
#
# print(test())
# nolocal: 只能用于局部变量。找上层中离当前函数最近一层的局部变量
# 声明了nolocal,的内部函数的变量修改会影响到离当前函数最近一层的局部变量
# 对全局无效,对最近一层的局部变量有效
# 对比global,只能修改全局变量的值
# a =1
# def test():
# a = 1
# def other():
# b =2
# print(a)
# print('other')
# def other1():
# nonlocal a # 声明了一个上面第一层局部变量
# a += 1
# print('other1')
# other1()
# other()
# print('局部A:',a)
# print(test())
# print('全局a :',a)
#
# def test():
# print(123)
#
# #test() # 函数名就是内存地址
# test1 = test # 函数名可以赋值
# print(test1,test)
#
# l = [test, test1] # 函数名可以作为容器类型的元素,如列表,元祖,字典等里的元素
# print (l)
# for i in l:
# i()
# def test():
# print(123)
#
# def test_one(t):
# t()
# return t # 函数名可以作为函数的返回值
#
# test_one(test) # 函数名可以作为函数的参数
# a = test_one(test) # 都是指向123的内存地址
# a()
# 闭包: 嵌套函数,内部函数要调用外部函数的变量
# 如果嵌套函数不调用a,则只是一个嵌套函数
# def test():
# a = 1
# def tset_a():
# b = 2
# print(a)
# print(b)
# def test():
# a = 1
# def test_a():
# print(a)
# return test_a
#
# aa = test()
# aa()