day4----函数-闭包-装饰器
本文档内容:
一 python中三种名称空间和作用域
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':}
- {'__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()
---------------------------------------------------------------------------------回顶部----------------------------------------------------------------------------------------------------------------------------
day4----函数-闭包-装饰器的更多相关文章
- python函数闭包-装饰器-03
可调用对象 callable() # 可调用的(这个东西加括号可以执行特定的功能,类和函数) 可调用对象即 callable(对象) 返回为 True 的对象 x = 1 print(cal ...
- 【Python3的命名空间与作用域,闭包函数,装饰器】
一.命名空间与作用域 命名空间是名字和对象的映射,就像是字典,key是变量名,value是变量的值 1.命名空间的定义 name='egon' #定义变量 def func(): #定义函数 pass ...
- python学习笔记-day4笔记 常用内置函数与装饰器
1.常用的python函数 abs 求绝对值 all 判断迭代器中所有的数据是否为真或者可迭代数据为空,返回真,否则返回假 any ...
- Python之函数对象、函数嵌套、名称空间与作用域、闭包函数、装饰器
目录 一 函数对象 二 函数的嵌套 三 名称空间和作用域 四 闭合函数 五 装饰器 一.函数对象 1.函数是第一类对象 #第一类对象的特性:# 可以被引用 # 可以当做参数传递 # 返回值是函数 # ...
- day11 闭包函数和装饰器
1.函数不是新知识点 主要是学习函数的用法 在面向对象编程中,一切皆对象,函数也不例外 具体的表现 1.函数可以引用 2.函数可以作为函数的参数 3.函数可以作为函数的返回值 4.可以被存储到容器类型 ...
- python基础-闭包函数和装饰器
闭包函数和装饰器 闭包函数 概念:在函数中(嵌套)定义另一个函数时,内部函数引用了外层函数的名字. 特性 闭包函数必须在函数内部定义 闭包函数可引用外层函数的名字 闭包函数是函数嵌套.函数对象.名称空 ...
- day11_7.11 闭包函数与装饰器
补充: callable 代表可调用的,加括号可以执行.(函数或者类) import this 查看python之禅 一.闭包函数 所谓闭包函数,就是定义在函数内部的函数,也就是函数定义的嵌套.而在 ...
- CSIC_716_20191112【闭包函数和装饰器】
闭包函数 什么是闭包函数:闭包函数是函数嵌套.函数对象.名称空间和作用域的集合体. 闭包函数必须在函数内部定义,闭包函数可以引用外层函数的名字. # _*_ coding: gbk _*_ # @Au ...
- Python_oldboy_自动化运维之路_函数,装饰器,模块,包(六)
本节内容 上节内容回顾(函数) 装饰器 模块 包 1.上节内容回顾(函数) 函数 1.为什么要用函数? 使用函数之模块化程序设计,定义一个函数就相当于定义了一个工具,需要用的话直接拿过来调用.不使用模 ...
- python学习之路-4 内置函数和装饰器
本篇涉及内容 内置函数 装饰器 内置函数 callable() 判断对象是否可以被调用,返回一个布尔值 1 2 3 4 5 6 7 8 9 10 11 num = 10 print(callabl ...
随机推荐
- R3注入的四种方式
DLL注入 1.首先要获取想要注入的进程句柄(OpenProcess) 2.从要注入的进程的地址空间中分配一段内存(VirtualAllocEx) 3.往分配的内存位置写入要注入的DLL名称(Writ ...
- Linux下批处理文件编写
linux下的批处理文件,基本就是shell脚本文件. 一.最简单的脚本书写方法为: 1.新建一个文件,名字为test(自己定义的名字) touch test.sh 2.在里面编写脚本 程序必须以下面 ...
- elasticsearch 聚合函数 max double精度损失bug
测试样例数据{ "size" : 0, "query" : { "bool" : { "must" : { " ...
- AXI Quad SPI
AXI Quad SPI 信息来源
- c++中计算程序执行时间
#include<iostream> #include<time.h> using namespace std; int main() { clock_t t1 = clock ...
- PI接口无法使用.net4以上的解决方法:无法嵌入互操作类型“PISDKClass”。请改用适用的接口。
Interop type 'PISDKClass' cannot be embedded. Use the applicable interface instead. .net开发中,有时候在引用某些 ...
- python之全局安装包管理工具pip
1.curl 'https://bootstrap.pypa.io/get-pip.py' > get-pip.py 2.sudo python get-pip.py 3.sudo easy_i ...
- Js之事件循环(执行机制)
js的执行机制是事件循环 什么是事件循环? js引擎在执行代码时,首先会将同步代码加入到主线程中,异步代码会放到event table中注册回调函数, 当主线程空闲之后,event table中的回调 ...
- IE10 下系统出现Unable to get property 'PageRequestManager' of undefined or null reference错误
在本地调试时没有任何问题,上传到测试服务器(win2003 framework 4.0)后打开网站出现Unable to get property 'PageRequestManager' of un ...
- [ZZ]面向对象编程,再见!
面向对象编程,再见!- 机器学习算法与自然语言处理 https://mp.weixin.qq.com/s/icXBlVOOYLvDnER7cEeCeg https://medium.com/@csca ...