python基础之闭包函数和装饰器
补充:全局变量声明及局部变量引用
python引用变量的顺序: 当前作用域局部变量->外层作用域变量->当前模块中的全局变量->python内置变量
global关键字用来在函数或其他局部作用域中使用全局变量,声明后可以在其他作用于中修改和使用
- x=1 #全局赋值变量
- def foo():
- global x #函数内部全局声明变量x
- x=1111111 #函数内部修改全局变量x
- print(x)
- foo()
- print(x)
global声明的变量在任何作用域都能够修改,所以一般非必要情况下要避免这种声明操作。
nonlocal关键字用来在函数或其他作用域中使用外层(非全局)变量,一般用在函数嵌套。
- def f1():
- # x=2
- def f2():
- x=3
- def f3():
- nonlocal x
- x=1111
- # print('f3',x)
- f3()
- print('f2',x)
- f2()
- # print('f1',x)
- f1()
如上,如果在f3的函数体内部不做nonlocal声明x,即将nonlocal x注释掉,那么函数体f2内的print将打印的结果是“f2 3”,声明后的结果为“f2 1111”。
闭包函数
闭包函数定义:
函数内部定义的函数称为内部函数,该内部函数包含对外部(上层)作用域,而不是对全局作用域名字的,那么该内部函数称为闭包函数
定义闭包函数:
- 定义闭包函数的基本形式
- def 外部函数名():
- 内部函数需要的变量
- def 内部函数(): #基本函数
- 引用外部的变量
- return 内部函数 #不加括号,返回内存地址
闭包函数指的是内部函数
闭包函数包含对外部作用域的引用,而非全局作用域的引用
闭包函数的特点:自带向外的作用域,延迟计算(惰性计算,用到的时候计算)
示例:
- name='alex' #全局定义的变量
- def func():
- name='egon' #函数func调用的变量,外部作用域
- def bar(): #内部函数
- print(name) #内部函数bar打印name的作用域除了bar函数自己本身,还有func函数内部
- return bar #调用func函数时的返回值为bar函数本身,而非bar函数执行结果,返回的是bar函数的一段内存地址
- b=func() #b接收func函数的返回值,即bar函数的内存空间,现在的b就等于是bar
- print(b)
- b() #执行b即执行bar函数的print(name)打印操作,而非全局定义的name
- #print(b.__closure__[0].cell_contents) #返回作用域空间的第一个变量值
- #print(b.__closure__) #作用域空间信息
- 输出结果
- <function func.<locals>.bar at 0x0000021CA66CB8C8>
- egon
自带向外的作用域,即bar函数包含func函数的作用域,也包含bar本身的作用域,即bar能够调用name='egon'
作用域在函数定义的时候已经固定了,也就是说,无论在什么地方调用b(),b函数的作用域永远用的是bar函数定义时候的作用域。
装饰器基础
程序源代码的原则:对功能扩展开放,对修改源代码封闭
即可以在源代码的基础上扩展功能,而不能修改源代码(原因是,系统上线了修改源代码,改错了咋整)
装饰器就是用来进行源代码功能能扩展的一种实现方式。
装饰器本质上是任意可调用的对象,目前能够理解的就是是函数,而被装饰的对象也可以是任意可调用的对象。
装饰器功能:是在不修改被装饰对象源代码以及被装饰对象的调用方式的前提下,为其添加新功能
装饰器原则:不修改源代码,不修改调用方式,还要能够增加新功能
示例一:当调用函数index时候,随机等待0-4秒打印hello world
- #原功能
- import time
- import random
- def index():
- time.sleep(random.randrange(1,5))
- print('hello world')
- index()
示例二:扩展功能统计index的执行时间,包括随机等待的时间
- import time
- import random
- def index_new(func):
- def timmer():
- start_time=time.time()
- func()
- stop_time=time.time()
- print('time:%s' %(stop_time-start_time))
- return timmer
- def index(): #源代码并不改变
- time.sleep(random.randrange(1,5))
- print('hello world')
- index=index_new(index)
- index()
- 输出结果:
- hello world
- time:3.000032663345337
示例三:装饰器调用语法
- def index_new(func):
- def timmer():
- start_time=time.time()
- func()
- stop_time=time.time()
- print('time:%s' %(stop_time-start_time))
- return timmer
- #使用@符号进行调用
- @index_new #index=index_new(index)
- def index():
- time.sleep(random.randrange(1,5))
- print('hello world')
- index()
示例四:定义多个装饰器,增加多个功能模块
- import time
- import random
- #装饰器1:计时模块
- def timmer(func):
- def wrapper():
- start_time = time.time()
- func()
- stop_time=time.time()
- print('run time is %s' %(stop_time-start_time))
- return wrapper
- #装饰器2:认证模块
- def auth(func):
- def deco():
- name=input('name: ')
- password=input('password: ')
- if name == 'egon' and password == '123':
- print('login successful')
- func() #wrapper()
- else:
- print('login err')
- return deco
- #被装饰函数
- @auth #index=auth(wrapper) #index=deco #index=auth(wrapper) #index=deco
- @timmer #index=timmer(index) #index=wrapper
- def index():
- # time.sleep(random.randrange(1,5))
- time.sleep(3)
- print('welecome to index page')
- #并没有调用任何装饰器
- def home():
- time.sleep(random.randrange(1,3))
- print('welecome to HOME page')
- index() #deco()
- home()
当要调用多个装饰器的时候,调用的顺序是,谁先执行就先调用哪一个,顺序是从上而下,但是内部计算的顺序是从下而上的
示例五:源代码需要传入参数的,以及需要返回值的
- import time
- import random
- #装饰器
- def timmer(func):
- def wrapper(*args,**kwargs): #*args和**kwargs能够接收任意的参数,并且可以不存在,接收后原封不动传入到func调用的函数
- start_time = time.time()
- res=func(*args,**kwargs) #返回值赋值,需要传入的函数有返回值才行
- stop_time=time.time()
- print('run time is %s' %(stop_time-start_time))
- return res #抛出返回值
- return wrapper
- #被装饰函数
- @timmer
- def index():
- time.sleep(random.randrange(1,5))
- print('welecome to index page')
- @timmer
- def home(name):
- time.sleep(random.randrange(1,3))
- print('welecome to %s HOME page' %name)
- return 123123123123123123123123123123123123123123
- res1=index()
- print('index return %s' %res1)
- res2=home('egon') #wraper()
- print('home return %s' %res2)
python基础之闭包函数和装饰器的更多相关文章
- Python基础(7)闭包函数、装饰器
一.闭包函数 闭包函数:1.函数内部定义函数,成为内部函数, 2.改内部函数包含对外部作用域,而不是对全局作用域名字的引用 那么该内部函数成为闭包函数 #最简单的无参闭包函数 def func1() ...
- Python基础(闭包函数、装饰器、模块和包)
闭包函数 格式: def 函数名1(): def 函数名2(): 变量 = 值 return 变量 return 函数名2 func = 函数名1() key = func()
- python基础之闭包函数与装饰器
闭包函数: 什么是闭包函数: 闭指的是定义在一个函数内部 包指的是该函数包含对外部作用域(非全局作用域)名字的引用 def counter(): n=0 def incr(): nonlocal n ...
- python 基础篇 11 函数进阶----装饰器
11. 前⽅⾼能-装饰器初识本节主要内容:1. 函数名的运⽤, 第⼀类对象2. 闭包3. 装饰器初识 一:函数名的运用: 函数名是一个变量,但他是一个特殊变量,加上括号可以执行函数. ⼆. 闭包什么是 ...
- python基础-闭包函数和装饰器
闭包函数和装饰器 闭包函数 概念:在函数中(嵌套)定义另一个函数时,内部函数引用了外层函数的名字. 特性 闭包函数必须在函数内部定义 闭包函数可引用外层函数的名字 闭包函数是函数嵌套.函数对象.名称空 ...
- day11 闭包函数和装饰器
1.函数不是新知识点 主要是学习函数的用法 在面向对象编程中,一切皆对象,函数也不例外 具体的表现 1.函数可以引用 2.函数可以作为函数的参数 3.函数可以作为函数的返回值 4.可以被存储到容器类型 ...
- Python之函数对象、函数嵌套、名称空间与作用域、闭包函数、装饰器
目录 一 函数对象 二 函数的嵌套 三 名称空间和作用域 四 闭合函数 五 装饰器 一.函数对象 1.函数是第一类对象 #第一类对象的特性:# 可以被引用 # 可以当做参数传递 # 返回值是函数 # ...
- 【Python3的命名空间与作用域,闭包函数,装饰器】
一.命名空间与作用域 命名空间是名字和对象的映射,就像是字典,key是变量名,value是变量的值 1.命名空间的定义 name='egon' #定义变量 def func(): #定义函数 pass ...
- day11_7.11 闭包函数与装饰器
补充: callable 代表可调用的,加括号可以执行.(函数或者类) import this 查看python之禅 一.闭包函数 所谓闭包函数,就是定义在函数内部的函数,也就是函数定义的嵌套.而在 ...
随机推荐
- Java Knowledge series 2
JVM Analysis & Design The object-oriented paradigm is a new and different way of thingking about ...
- 【Android学习入门】Android studio基本设置
1.背景设置 依次选择File->Settings-->Appearance & Behaviour->Apprearance,然后勾选 show line number. ...
- android listview 加载遇到的问题
http://blog.csdn.net/l_serein/article/details/7706338 转载: 描述一下场景: 菜单栏上有若干分类,点击每一个分类,ListView下分根据分类显示 ...
- [原创] Debian9上配置软件阵列
序言 软阵列是用软件实现的磁盘阵列. 准备工作 1. 更新系统 没啥,就他喵想用个最新的. apt update && apt upgrade 2. 安装mdadm 如果系统没有自带m ...
- Struts2_HelloWorld_6
为 eclipse 在编写 xml配置文件时提供提示,需要加上dtd或xls的标签定义文件的路径,具体操作: 1.Window——Preferences——XML Catalog 2.添加 dtd 文 ...
- Js 数据类型 Number()转型函数
alert(Number(true)); //转换为1,如果为false为0 alert(Number()); //25,数值型直接返回 alert(Number(null)); //0,空对象返回0 ...
- Codeforces Round #261 (Div. 2) - E (459E)
题目连接:http://codeforces.com/contest/459/problem/E 题目大意:给定一张有向图,无自环无重边,每条边有一个边权,求最长严格上升路径长度.(1≤n,m≤3 * ...
- css3弹性盒子
CSS3 弹性盒子(Flex Box) 弹性盒子是 CSS3 的一种新的布局模式. CSS3 弹性盒( Flexible Box 或 flexbox),是一种当页面需要适应不同的屏幕大小以及设备类型时 ...
- 数集合有多少个TOJ(2469)
题目链接:http://acm.tju.edu.cn/toj/showp2469.html 感觉这个题目有点问题,算了不管他了,反正A了. 这里要注意的是求这个集合有多少种,那么就是要剔除重复数后,再 ...
- SQL按时间段统计(5分钟统计一次访问量为例,oracle统计)
需求:统计当天的访问量,每五分钟采集一次 表结构中有日期字段,类型TIMESTAMP 如果,统计是采用每秒/分钟/小时/天/周/月/年,都非常容易实现,只要to_char日期字段然后group by分 ...