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…

【原理图操作】原理图更新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…

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

智能手机丢失 数据安全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;系统…

共享没有权限访问权限_如何与家人共享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;并且希望他们所有人都可以…

使用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解码流程…

IntelliJ IDEA代码分屏显示

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

vscode重置应用程序_如何在Windows 10上重置应用程序的数据

vscode重置应用程序With Windows 10’s Anniversary Update, you can now reset an app’s data without actually uninstalling and reinstalling the app. This can fix problems when an app has gotten into a bad state, or just quickly restore an app to its default s…

程序报错与提示

2019独角兽企业重金招聘Python工程师标准>>> 我们在开发中, 为了程序的规范性,把报错级别,调的比较高NOTICE级别的也报出来,有助于我们快速定位错误和代码规范&#xff0c;但是,在产品上线后,网站运营过程中,就不宜报这么多错. 1:这种错误给客户的印象不好 2:在报错…

dock怎么自定义_如何自定义和调整Mac的Dock

dock怎么自定义The macOS dock normally appears at the bottom of your screen, but it doesn’t have to. The dock is customizable in quite a few ways you might not be aware of, especially if you’re a new Mac user. macOS坞站通常显示在屏幕底部&#xff0c;但不是…

ios 轻扫手势_轻扫即可快速删除iOS计算器中的数字

ios 轻扫手势iOS’ built-in calculator is a basic, simple-to-use calculator that’s very handy for doing some quick calculations, such as calculating the tip on your restaurant bill. It’s also useful for longer, more complicated calculations. However, ther…

游戏安全资讯精选 2017年第十期 英国彩票网遭遇DDoS攻击,中断90分钟 DNSMASQ多高危漏洞公告 阿里云协助警方破获国内最大黑客攻击案,攻击峰值690G...

【本周游戏行业DDoS攻击态势】 国庆期间&#xff0c;针对游戏行业的DDoS攻击放缓&#xff0c;攻击者也在放“小长假”&#xff0c;10月8日超过500G的攻击可视作攻击猛烈度恢复的表现。 【游戏安全动态】 英国彩票网遭遇DDoS攻击&#xff0c;中断90分钟 点击查看原文 点评&#…

02 jmeter 简单发送http请求

一、新建http请求模板1、测试计划2、右键Threads(users)-线程组3、右键sample-http请求4、右键监听器-查看结果树5、右键监听器-查看聚合报告二、编辑http请求内容三、设置并发用户1&#xff1a;虚拟用户数&#xff1b; 2&#xff1a;加载用户时间&#xff1b;3、每个用户循环次…

java调用siri 语言_如何更改Siri的声音,口音,性别和语言

java调用siri 语言Most of us are familiar with Siri as an American female voice. What you may not realize is that you can actually change Siri to have a different accent, gender, and language. 我们大多数人都熟悉Siri&#xff0c;这是一种美国女性声音。 您可能没…