1.1名称空间:
当程序运行时,代码从上至下依次执行,它会将变量与值得关系存储在一个空间中,这个空间
也叫命名空间。例如:name='xingchen'
当程序遇到函数时,它会将函数名存在内存中,函数内部的变量和逻辑暂时不关心;
当函数执行时,内存会临时开辟一个空间,存放函数体里面的代码(变量,代码等),这个空间叫临时名称空间
也叫局部名称空间。
函数外面访问不到临时空间的内容;随着函数的执行完毕,临时空间会释放掉。
python中名称空间分三种:
内置名称空间
全局名称空间
局部名称空间
作用域:
全局作用域:
内置名称空间
全局名称空间
局部作用域:
局部名称空间
加载顺序:
内置名称空间 ---》全局名称空间(程序执行时) ---》局部名称空间(函数执行时)
取值顺序:单向不可逆
局部名称空间 ---》全局名称空间 ----》内置名称空间
1.2 globals和locals
print(globals() ) 返回的是全局作用域里面的变量与其值,是一个字典
print(locals()) 返回的是当前的局部变量与其值,也是一个字典
例如:
def func1():
a=1
print(a)
print(locals())
print(globals())
func1()
其结果为:
1 {'a': 1} {'__name__': '__main__', '__doc__': None, '__package__': None, '__loader__': <_frozen_importlib_external.SourceFileLoader object at 0x0000024FD014B240>, '__spec__': None, '__annotations__': {}, '__builtins__': <module 'builtins' (built-in)>, '__file__': 'D:/PycharmProjects-x/s22day03/day4/lianxi.py', '__cached__': None, 'time': <module 'time' (built-in)>, 'func1': <function func1 at 0x0000024FD0056048>}
1.3 global和nonlocal
global:声明一个全局变量,可以用作局部变量的关键字来修改或赋值给全局变量,
但是:对可变数据类型(list,dict,set)可以直接引用不用通过global。如果默认参数是一个可变的数据类型,那么他在内存中永远是一个
例如:下面的list就是可变数据类型,因此就不用global
# 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']
# print('list1=%s'%list1)
# print('list2=%s'%list2)
# print('list3=%s'%list3)
其结果为:
[10,a]
[123]
[10,a]
nonlocal:在局部作用域中,对其父级作用域(或者更外层作用域)进行变量赋值或者修改,但是不能修改全局作用域
例如:
def func1(): a=1 def func2(): b=10 def func3(): nonlocal a,b a=a+1 b=b+1 print(a,b) #结果为 2,11 func3() print(a,b) #结果为 2,11,func2函数的b被引用了 func2() print(a) #结果为 2,这里的变量a被引用了,但是b不是在这里面引用的,所以打印b会报错 func1()
函数名的本质就是函数的内存地址
1 函数可以被引用
例如:
def func1(): print('in func1') f=func1 print(f) 结果为:<function func1 at 0x000001E9313C6048>
2 函数可以作为容器类元素
例如
def func1(): print('f1') def func2(): print('f2') l1=[func1,func2] l2={'f1':func1,'f2':func2} l1[0]() l2['f2']()
3 函数可以作为返回值
def f1(): print('f1') def func1(argv): argv() return argv f = func1(f1) f()
其他: 第一类对象
第一类对象(first-class object)指
1.可在运行期创建
2.可用作函数参数或返回值
3.可存入变量的实体。
内部函数包含对外部作用域而非全局作用域变量的引用,该内部函数称为闭包函数,一般用于装饰器或者网络爬取内容
判断闭包函数的方法__closure__
例如:
def func(): name = 'eva' def inner(): print(name) print(inner.__closure__) #结果中函数含有cell元素,否则为none return inner f = func() f()
闭包函数一个例子
def line_conf(a, b): def line(x): return a * x + b return line
装饰器的本质是一个python函数,基于闭包函数,让其他的函数在不改变源码和调用方式的前提下,增加新的功能
装饰器的应用场景:比如插入日志,性能测试,事务处理,缓存等等场景。
下面看看装饰器的形成过程:
原始的代码
import time # print(time.time()) # 1527326532.2688255 # def func1(): # time.sleep(0.3) # print('非常复杂......') # # start_time = time.time() # func1() # end_time = time.time() # print('此函数的执行效率%s' %(end_time-start_time))
# 改版1:我要封装到一个函数中
# def func1(): # time.sleep(0.3) # print('非常复杂......') # # def func2(): # time.sleep(0.3) # print('特别复杂......') # # func1() # func2()
# # 改版2:被测试函数当参数传入,可以测试多个函数的执行效率
# def timmer(f): # start_time = time.time() # f() # end_time = time.time() # print('此函数的执行效率%s' %(end_time-start_time)) # # timmer(func1) # timmer(func2)
# 改版3::测试函数执行效率的同时,不要改变原函数的调用方式。
# def func1(): # time.sleep(0.3) # print('非常复杂......') # def func2(): # time.sleep(0.3) # print('特别复杂......') # # func1() # # func2() # def timmer(f): # start_time = time.time() # f() # end_time = time.time() # print('此函数的执行效率%s' % (end_time - start_time)) # f1 = func1 # func1 = timmer # # func1(f1) # timmer(func1)
# 改版4::改版3虽然大体上满足了我的要求,但是增加两行代码,
# 而且多了参数,不好,继续改,尽量不添加其他代码,而且做到调用时一模一样
# 最简单的装饰器。
# def func1(): # time.sleep(0.3) # print('非常复杂......') # def func2(): # time.sleep(0.3) # print('特别复杂......') # # func1() # # func2() # # def timmer(f): # f = func1 函数名 # def inner(): # start_time = time.time() # f() # end_time = time.time() # print('此函数的执行效率%s' % (end_time - start_time)) # return inner # # func1 = timmer(func1) # inner # func2 = timmer(func2) # inner # func1() # inner() # func2()
# 改版5::改版4每次测试一个函数的执行效率时,都需要加一行 func1 = timmer(func1)代码,麻烦
# python提出了一个语法糖 @。
# def timmer(f): # f = func1 函数名 # def inner(): # start_time = time.time() # f() # end_time = time.time() # print('此函数的执行效率%s' % (end_time - start_time)) # return inner # # @timmer # func1 = timmer(func1) inner # def func1(): # time.sleep(0.3) # print('非常复杂......') # # func1() # inner()
# 改版6:被装饰的函数肯定要有参数的,你现在不能满足,解决这个问题。
# 被装饰的函数带参数的装饰器
# def timmer(f): # f = func1 函数名 # def inner(*args,**kwargs): # args = (1,2),kwargs {sex:'nv',name:'alex'} # start_time = time.time() # f(*args,**kwargs) # f(1,2,,sex='nv',name='alex') # end_time = time.time() # print('此函数的执行效率%s' % (end_time - start_time)) # return inner # # @timmer # func1 = timmer(func1) inner # def func1(a,b): # time.sleep(0.3) # print(a,b) # print('非常复杂......') # # # @timmer # func1 = timmer(func1) inner # def func2(a,b,name,sex='man'): # f(1,2,,sex='nv',name='alex') # time.sleep(0.3) # print(a,b,sex,name) # print('非常复杂......') # # func2(1,2,sex='nv',name='alex') # inner()
# 改版7:被装饰的函数肯定要有返回值的,解决这个问题。
# 被装饰的函数带参数且有返回值的装饰器
# def timmer(f): # f = func2 函数名 # def inner(*args,**kwargs): # args = (1,2),kwargs {sex:'nv',name:'alex'} # start_time = time.time() # ret = f(*args,**kwargs) # f(1,2,,sex='nv',name='alex') # end_time = time.time() # print('此函数的执行效率%s' % (end_time - start_time)) # return ret # return inner # @timmer # func1 = timmer(func1) inner # def func2(a,b,name,sex='man'): # f(1,2,,sex='nv',name='alex') # time.sleep(0.3) # print(a,b,sex,name) # print('非常复杂......') # return 666 # # print(func2(1,2,sex='nv',name='alex')) # inner() 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 func2(a,b,name,sex='man'): # time.sleep(0.3) # print(a,b,sex,name) # print('非常复杂......') # return 666 # # ret1 = func2(1,2,sex='nv',name='alex') # print(ret1)
至此装饰器的固定结构如下
def timer(func): def inner(*args,**kwargs): '''执行函数之前要做的''' re = func(*args,**kwargs) '''执行函数之后要做的''' return re return inner
但是如何函数有很多,如何取消他们呢,以后如果又加上呢---带参数的装饰器模型
def outer(flag): def timer(func): def inner(*args,**kwargs): if flag: print('''执行函数之前要做的''') re = func(*args,**kwargs) if flag: print('''执行函数之后要做的''') return re return inner return timer @outer(False) #改为false是不执行装饰器内的内容 def func(): print(111) func()
如果多个装饰器装饰一个函数呢
def wrapper1(func): def inner(): print('wrapper1 ,before func') func() print('wrapper1 ,after func') return inner def wrapper2(func): def inner(): print('wrapper2 ,before func') func() print('wrapper2 ,after func') return inner @wrapper1 @wrapper2 def f(): print('in f') f()
其结果为:
wrapper1 ,before func wrapper2 ,before func in f wrapper2 ,after func wrapper1 ,after func
装饰器的另外一种方法:
import functools def wrapper(func): @functools.wraps(func) def inner(*args, **kwargs): print('我是装饰器') return func(*args,**kwargs) print('--------') return inner @wrapper def index(): print('我是被装饰函数') return None
index()
---------------------------------------------------------------------------------回顶部----------------------------------------------------------------------------------------------------------------------------