名称空间与作用域
1.变量储存在一个内存空间中
2.当程序运行的时候代码从上到下依次执行,它会将变量与值的关系存储在一个空间中,这个空间叫名称空间,命名空间,全局名称空间
3.当程序遇到函数时,它会将函数名存在内存中,函数体漠不关心
4.当程序执行的时候,内存会临时开辟一个空间,存放函数体里的代码(变量,代码等)
5.函数外面访问不到临时空间的内容,随着函数执行完毕,临时名称空间会被释放掉,向这个临时开辟的空间也叫临时名称空间,也叫局部名称空间
- python名称空间分为三种:
1.内置名称空间
2.全局名称空间
3.局部名称空间 按照作用域分为两种:
全局作用域
1.内置名称空间 2.全局名称空间
局部作用域
1.局部名称空间
- 加载顺序
内置名称空间—全局名称空间(当程序执行时)—局部名称空间(函数调用时) 取值顺序
局部名称空间(函数调用时)—全局名称空间(当程序执行时)—内置名称空间
注:取值顺序是单向不可逆的1.取值又叫引用,局部名称空间可以临时像全局名称空间引用,但是无法修改 2.取值是从小到大取值LEGB - L=最里层的局部作用域 - E=父亲级别的局部作用域 - G=全局作用域中的全局名称空间 - B=全局作用域中的内置名称空间
内置函数globals和locals的方法:
globles
globales返回一个字典,字典里的内容是全局名称空间的内容
locals
locals返回一个字典,当前位置的所有变量(看locals的位置是否在函数体里还是在全局里)
#1.
print(globals())
print(locals())
#打印结果:
{'__name__': '__main__', '__doc__': None, '__package__': None, '__loader__': <_frozen_importlib_external.SourceFileLoader object at 0x004DB4B0>, '__spec__': None, '__annotations__': {}, '__builtins__': <module 'builtins' (built-in)>, '__file__': 'E:/python/day04/1.py', '__cached__': None}
{'__name__': '__main__', '__doc__': None, '__package__': None, '__loader__': <_frozen_importlib_external.SourceFileLoader object at 0x004DB4B0>, '__spec__': None, '__annotations__': {}, '__builtins__': <module 'builtins' (built-in)>, '__file__': 'E:/python/day04/1.py', '__cached__': None}
#2.
def func():
a = 12
b = 20
print(locals())
print(globals())
func()
#打印结果:
{'b': 20, 'a': 12}
{'__name__': '__main__', '__doc__': None, '__package__': None, '__loader__': <_frozen_importlib_external.SourceFileLoader object at 0x0044B4B0>, '__spec__': None, '__annotations__': {}, '__builtins__': <module 'builtins' (built-in)>, '__file__': 'E:/python/day04/1.py', '__cached__': None, 'func': <function func at 0x0040B660>}
关键字global和nonlocal的方法:
- global
1.global可以引用全局变量,并且改变全局变量
2.在局部作用域声明一个全局变量 - nonlocal
1.不能操作全局变量
2.在局部作用域中,对父级作用域(或者更外层作用域非全局作用域)的变量进行引用和修改,并且引用的哪层,从那层及以下此变量全部发生改变。
- global
注:对于可变的数据类型list,dict,set,不用引用global,nonlocal
注:如果默认参数是一个可变的数据类型,那么他在内存中永远是一个。
#1.第一种情况:
def extendList(val,list=[]):
list.append(val)
return list
list1 = extendList(10)
print('list1=%s'%list1) # [10,]
list2 = extendList(123,[])
print('list2=%s'%list2) # [123,]
list3 = extendList('a')
print('list3=%s'%list3) #[10,'a']
打印结果为:
list1=[10]
list2=[123]
list3=[10, 'a']
#2.第二种:
def extendList(val,list=[]):
list.append(val)
return list
list1 = extendList(10)
list2 = extendList(123,[])
list3 = extendList('a')
print('list1=%s'%list1)
print('list2=%s'%list2)
print('list3=%s'%list3)
打印结果为:
list1=[10, 'a']
list2=[123]
list3=[10, 'a']
因为:如果默认参数是一个可变的数据类型,那么他在内存中永远是一个。
1.global实例:
def func():
global a
a = 3
func()
print(a)
#打印结果为:3
count = 1
def search():
global count
count = 2
search()
print(count)
#打印结果为2
2.nonloacl实例:
def add_b():
b = 42
def do_global():
b = 10
print(b)
def dd_nonlocal():
nonlocal b
b = b + 20
print(b)
dd_nonlocal() #30
print(b) #30
do_global() #10
print(b)
add_b()
#打印结果为:
10
30
30
42
函数
- 函数的嵌套与调用:
#函数的嵌套
def max2(x,y):
m = x if x>y else y
return m
def max4(a,b,c,d):
res1 = max2(a,b)
res2 = max2(res1,c)
res3 = max2(res2,d)
return res3
#函数的调用
max4(1,2,3,4)
- 函数名的本质
1.打印函数名
def func():
print('in func')
f = func
print(f)
#打印结果为:<function func at 0x0020B660>
为一块内存地址
2.函数名可以作为容器类数据的元素
def func1():
print(111)
def func2():
print(222)
def func3():
print(333)
l1 = [func1, func2, func3]
for i in l1:
i()
#打印结果为:
111
222
333
3.函数名可以作为函数的参数
def func1():
print(111)
def func2(x):
print(x)
x()
print(222)
func2(func1)
#打印结果为:
<function func1 at 0x0021B660>
111
222
4.函数名可以作为函数的返回值
def func1():
return 111
def func2(x): # x = func1
print(222)
return x
ret = func2(func1) # func1
print(ret())
print(ret)
#打印结果为:
222
111
<function func1 at 0x002BB660>
总结:
函数名的应用,第一类对象- 函数名打印的出来的是个内存地址,加()号就可以运行 - 函数名可以作为容器类型内的元素 - 函数名可以作为传递的参数 - 函数名可以作为函数的返回值,return把值给函数的执行者
闭包函数
- 内层函数对外层函数非全局变量的引用,就叫做闭包 - 判断是否是闭包:__closure__ - 如果python解释器遇到了闭包,他有个机制,这个闭包不会随着函数的结束而释放 - 装饰器@语法糖,装饰器放在需要装饰的函数的上边,利用的就是闭包函数
装饰器:
#测试func1函数的执行时间
def timmer(f):
def inner(*args,**kwargs):
start_time = time.time()
ret = f(*args,**kwargs)
end_time = time.time()
print('此函数的执行效率%s' % (end_time - start_time))
return ret
return inner
@timmer
def func1():
time.sleep(0.3)
print('非常复杂......')
func1()
#格式为:
def wrapper(f):
def inner(*args,**kwargs):
"""被装饰函数执行之前的操作"""
ret = f(*args,**kwargs)
"""被装饰函数执行之后的操作"""
return ret
return inner
# 装饰器 本质就是闭包
# 装饰器根本作用:在不影响原函数执行的基础上,增加一些额外的功能登录认证,打印日志等等。
内裤可以用来遮羞,但是到了冬天它没法为我们防风御寒,聪明的人们发明了长裤,有了长裤后宝宝再也不冷了,装饰器就像我们这里说的长裤,在不影响内裤作用的前提下,给我们的身子提供了保暖的功效。