day4----函数-闭包-装饰器

day4----函数-闭包-装饰器

本文档内容:

1 python中三种名称空间和作用域

2 函数的使用

3 闭包

4 装饰器

一 python中三种名称空间和作用域

1.1名称空间:

当程序运行时,代码从上至下依次执行,它会将变量与值得关系存储在一个空间中,这个空间
也叫命名空间。例如:name='xingchen'
当程序遇到函数时,它会将函数名存在内存中,函数内部的变量和逻辑暂时不关心;
当函数执行时,内存会临时开辟一个空间,存放函数体里面的代码(变量,代码等),这个空间叫临时名称空间
也叫局部名称空间。
函数外面访问不到临时空间的内容;随着函数的执行完毕,临时空间会释放掉。
View Code

python中名称空间分三种:
  内置名称空间
  全局名称空间
  局部名称空间
作用域:
  全局作用域:
    内置名称空间
    全局名称空间
局部作用域:
    局部名称空间
加载顺序
内置名称空间 ---》全局名称空间(程序执行时) ---》局部名称空间(函数执行时)
取值顺序:单向不可逆
局部名称空间 ---》全局名称空间 ----》内置名称空间

1.2  globals和locals

print(globals() ) 返回的是全局作用域里面的变量与其值,是一个字典

print(locals())   返回的是当前的局部变量与其值,也是一个字典

例如:

def func1():a=1print(a)print(locals())print(globals())
func1()
View Code

其结果为:

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>}
View Code

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]
View Code 

nonlocal:在局部作用域中,对其父级作用域(或者更外层作用域)进行变量赋值或者修改,但是不能修改全局作用域

例如:

def func1():a=1def func2():b=10def func3():nonlocal a,ba=a+1b=b+1print(a,b)   #结果为 2,11
        func3()print(a,b)       #结果为 2,11,func2函数的b被引用了
    func2()print(a)        #结果为 2,这里的变量a被引用了,但是b不是在这里面引用的,所以打印b会报错
func1()
View Code

二函数的使用

函数名的本质就是函数的内存地址

1 函数可以被引用

例如:

def func1():print('in func1')
f=func1
print(f)
结果为:<function func1 at 0x000001E9313C6048>
View Code

2 函数可以作为容器类元素

例如

def func1():print('f1')def func2():print('f2')l1=[func1,func2]
l2={'f1':func1,'f2':func2}l1[0]()
l2['f2']()
View Code

3 函数可以作为返回值

def f1():print('f1')def func1(argv):argv()return argvf = func1(f1)
f()
View Code

其他: 第一类对象

第一类对象(first-class object)指
1.可在运行期创建
2.可用作函数参数或返回值
3.可存入变量的实体。
View Code

 三 闭包

内部函数包含对外部作用域而非全局作用域变量的引用,该内部函数称为闭包函数,一般用于装饰器或者网络爬取内容

判断闭包函数的方法__closure__

例如:

def func():name = 'eva'def inner():print(name)print(inner.__closure__) #结果中函数含有cell元素,否则为none
return inner 
f = func() 
f()
View Code

四 装饰器

 装饰器的本质是一个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))
View Code

# 改版1:我要封装到一个函数中

# def func1():
#    time.sleep(0.3)
#    print('非常复杂......')
#
# def func2():
#    time.sleep(0.3)
#    print('特别复杂......')
#
# func1()
# func2()
View Code

# # 改版2:被测试函数当参数传入,可以测试多个函数的执行效率

# def timmer(f):
#    start_time = time.time()
#   f()
#    end_time = time.time()
#    print('此函数的执行效率%s' %(end_time-start_time))
#
# timmer(func1)
# timmer(func2)
View Code

# 改版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)
View Code

# 改版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()
View Code

# 改版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()
View Code

# 改版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()
View Code

# 改版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 retreturn 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)
View Code
至此装饰器的固定结构如下
def timer(func):def inner(*args,**kwargs):'''执行函数之前要做的'''re = func(*args,**kwargs)'''执行函数之后要做的'''return rereturn inner
View Code

 但是如何函数有很多,如何取消他们呢,以后如果又加上呢---带参数的装饰器模型

def outer(flag):def timer(func):def inner(*args,**kwargs):if flag:print('''执行函数之前要做的''')re = func(*args,**kwargs)if flag:print('''执行函数之后要做的''')return rereturn innerreturn timer@outer(False)  #改为false是不执行装饰器内的内容
def func():print(111)func()
View Code

如果多个装饰器装饰一个函数呢

def wrapper1(func):def inner():print('wrapper1 ,before func')func()print('wrapper1 ,after func')return innerdef wrapper2(func):def inner():print('wrapper2 ,before func')func()print('wrapper2 ,after func')return inner@wrapper1
@wrapper2
def f():print('in f')
f()
View Code

其结果为:

wrapper1 ,before func
wrapper2 ,before func
in f
wrapper2 ,after func
wrapper1 ,after func
View Code

 装饰器的另外一种方法:

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()

 

 

 

---------------------------------------------------------------------------------回顶部----------------------------------------------------------------------------------------------------------------------------

posted on 2018-05-30 10:16 dawn-liu 阅读(...) 评论(...) 编辑 收藏

转载于:https://www.cnblogs.com/mmyy-blog/p/9109425.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/280205.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

滤波器和均衡器有什么区别_什么是均衡器,它如何工作?

滤波器和均衡器有什么区别It’s in your car, home theater system, phone, and audio player but it doesn’t have an instruction manual. It’s an equalizer, and with a little know-how you can tweak your audio and fall in love with it all over again. 它在您的汽车…

网络视频监控与人脸识别

明天又要去面试了&#xff0c;趁次机会也将以前做的东西总结一下&#xff0c;为以后理解提供方便&#xff0c;也再加深下印象。 网络视频监控与人脸识别主要由三个程序组成&#xff1a;1、视频采集与传输程序&#xff1b;2、接受与显示程序&#xff1b;3、人脸识别程序。下面就…

esxi.主机配置上联端口_为什么现代的电脑机箱仍然具有USB 2.0端口?

esxi.主机配置上联端口With USB 3.0 becoming more prevalent with each passing year now, you may have found yourself wondering why modern computers still have USB 2.0 ports built into them. With that in mind, today’s SuperUser Q&A post has the answers to…

使用命令导入、导出mysql数据

1.导出全部数据库 利用mysqldump的—all-databases参数可以一口气把你数据库root用户下的所有数据库一口气导出到一个sql文件里。然后&#xff0c;重装系统后使用source命令可以再一口气倒回来。 需要确定mysql安装的路径&#xff1a;本机是&#xff1a;C:\Program Files\MySQL…

面试--跨域--cors

cors是什么 cors 跨域资源共享 Cross-origin resource sharing是一种跨域的解决方案 它允许浏览器向跨源服务器&#xff0c;发出XMLHttpRequest请求&#xff0c;从而克服了AJAX只能同源使用的限制。 但是需要浏览器的支持。值得注意的是&#xff1a;整个CORS通信过程&#xff0…

【原理图操作】原理图更新PCB时未改动元器件布局变动问题?

转载PCB布局、布线完工之后&#xff0c;由于设计功能&#xff0c;发现不完善时, 原理图部分功能需要改动&#xff0c;再改原理图&#xff0c;修改完成后&#xff0c;导入PCB过程中&#xff0c;发现PCB中未改动&#xff08;部分&#xff09;的元器件 布局发生了变化&#xff0c;…

关闭edge任务栏预览_如何在Microsoft Edge中关闭选项卡预览

关闭edge任务栏预览Now that it has extension support, Microsoft Edge is becoming a more and more viable browser. One feature people seem to either love or hate is the pop-up preview you get when you hover over a tab. There’s no built-in setting that lets y…

oracle 创建view时,授权给用户

解决方法&#xff1a; 以dba用户登录 sqlplus / as sysdba 赋予scott用户创建VIEW的权限 grant create view to scott 以scott用户登录oracle conn scott/tiger 创建视图成功 CREATE OR REPLACE VIEW myview AS 转载于:https://www.cnblogs.com/523823-wu/p/7635436.html

[BZOJ 1072] 排列perm

Link&#xff1a; BZOJ 1072 传送门 Solution&#xff1a; 一道直接next_permutation纯暴力就能过的题&#xff1f; 难道2007年时大家都不知道next_permutation这个函数吗 还是用复杂度更优的状压DP吧 设$dp[i][j]$为状态为$i$且对$d$余$j$的个数&#xff0c; 注意$dp[(1<&l…

智能手机丢失 数据安全_丢失智能手机时该怎么办

智能手机丢失 数据安全Phones get stolen or lost everyday. With a plethora of data ripe for identity-theft on it, a lost phone can easily make your blood run cold. Take a deep breath, How-To Geek will talk you through this. 手机每天都会被盗或丢失。 随着大量用…

程序员怎样成为一名架构师?

在今天的技术圈&#xff0c;可能随便遇到一个人递给你一张名片&#xff0c;title 就是某某架构师。架构师多如过江之鲫&#xff0c;也正是眼下业内一个有趣的现象。对于架构师&#xff0c;你有什么看法&#xff1f;什么是架构师&#xff1f;随便打开某招聘网站&#xff1a;系统…

C++设计模式之工厂模式(1)

关于设计模式的作用&#xff1a; “帮助我们将应用组织成容易了解&#xff0c;容易维护&#xff0c;具有弹性的架构&#xff0c;建立可维护的OO系统&#xff0c;要诀在于随时想到系统以后可能需要的变化以及应付变化的原则。” 具体可参考&#xff1a;https://www.cnblogs.com/…

共享没有权限访问权限_如何与家人共享SmartThings访问权限

共享没有权限访问权限If you have multiple people in your household and want them all to have access to SmartThings from their phones, here’s how to share access to SmartThings with anyone you want. 如果您的家庭中有多个人&#xff0c;并且希望他们所有人都可以…

PABX

自动用户小交换机;&#xff3b;私用自动交换分机&#xff3d; A private telephone exchange that automatically connects internal “branch” lines to the external circuits of a telephone system. 一种自动地将内部用户线连接到电话系统外线的专用电话交换机。 Private …

使用jquery+css实现瀑布流布局

虽然可以直接使用css实现瀑布流布局&#xff0c;但显示的方式有点问题&#xff0c;所以这儿就直接使用jquerycss来实现瀑布流布局&#xff0c;最终效果如下&#xff1a; 思路是通过将每个小块的position设置为relative&#xff0c;然后计算出在当前选择的列下应该上移的距离&am…

geek_How-To Geek正在寻找安全作家

geekThink you have the perfect combination of geek knowledge and writing skills? We’re looking for an experienced, security-focused writer to join our team. 认为您将怪胎知识和写作技能完美结合了吗&#xff1f; 我们正在寻找经验丰富&#xff0c;注重安全性的作…

AAC 文件解析及解码流程

OUTLINE&#xff1a; &#xff0a; AAC概述 &#xff0a; AAC规格简述 &#xff0a; AAC特点 &#xff0a; AAC音频文件解析 ——ADIF&#xff06;ADTS格式 ——ADIF&#xff06;ADTS头信息 ——ADIF&#xff06;ADTS数据信息 ——AAC文件处理流程 &#xff0a; AAC解码流程…

JDK8之Stream新特性

/***JDK8 Stream特性* Created by chengbx on 2018/5/27.* Java 8 中的 Stream 是对集合&#xff08;Collection&#xff09;对象功能的增强&#xff0c;它专注于对集合对象进行各种非常便利、高效的聚合操作&#xff08;aggregate operation&#xff09;&#xff0c;* 或者大…

鸡蛋学运维-2:Rsync同步配置步骤

说明&#xff1a;系统环境CentOS release 6.5 (Final) 2.6.32-431.el6.x86_64rsync server:配置步骤1、vi /etc/rsyncd.conf#Rsync server#created by lijianfeng 18:26 2017-9-24#rsyncd.conf start#uid rsyncgid rsyncuse chroot nomax connections 2000timeout 600pid…

IntelliJ IDEA代码分屏显示

转载于:https://www.cnblogs.com/EasonJim/p/9124809.html