闭包(closure)是函数式编程的重要的语法结构。

  定义:如果在一个内部函数里,对在外部作用域(但不是在全局作用域)的变量进行引用,那么内部函数就被认为是闭包(closure).

def outer():
x = 1
def inner():
print(x)
return inner
f = outer()
f()

inner就是内部函数,inner里引用了外部作用域的变量x(x在外部作用域outer里面,不是全局作用域),则这个内部函数inner就是一个闭包。

闭包=函数块+定义函数时的环境,inner就是函数块,x就是环境。

装饰器

  装饰器本质上是一个函数,该函数用来处理其他函数,它可以让其他函数在不需要修改代码的前提下增加额外的功能,装饰器的返回值也是一个函数对象。

  它经常用于有切面需求的场景,比如:插入日志、性能测试、事务处理、缓存、权限校验等应用场景。装饰器是解决这类问题的绝佳设计,有了装饰器,我们就可以抽离出大量与函数功能本身无关的雷同代码并继续重用。概括的讲,装饰器的作用就是为已经存在的对象添加额外的功能。

简单的装饰器函数:

@符号是装饰器的语法糖,在定义函数的时候使用,避免再一次赋值操作

import time
def shoe_time(f):
def inner():
start = time.time()
f()
end = time.time()
print(end-start)
return inner
@shoe_time #foo = shoe_time(foo)
def foo():
#start = time.time()
print("foo......")
time.sleep(2)
#end = time.time()
#print(end-start) #2.0001144409179688
#foo()
@shoe_time #bar = shoe_time(bar)
def bar():
# start = time.time()
print("bar......")
time.sleep(3)
#end = time.time()
#print(end-start) #3.001171588897705
#bar()
#shoe_time(foo) #2.0001142024993896
#shoe_time(bar) #3.001171588897705
foo() #foo...... # 2.0001144409179688
bar() # bar......
# 3.00017142295837

带参数的被装饰函数

#功能函数加参数
import time
def shoe_time(f):
def inner(x,y):
start = time.time()
f(x,y)
end = time.time()
print(end-start)
return inner
@shoe_time
def add(a,b):
print(a+b)
time.sleep(3)
#@shoe_time
# def foo():
# print("foo......")
# time.sleep(2)
# @shoe_time
# def bar():
# print("bar......")
# time.sleep(3)
#
add(1,3) #
#3.000171661376953 #不定长参数
import time
def shoe_time(f):
def inner(*x,**y):
start = time.time()
f(*x,**y)
end = time.time()
print(end-start)
return inner
@shoe_time
def add(*a,**b):
sum = 0
for i in a:
sum += i
print(sum)
time.sleep(3)
#@shoe_time
# def foo():
# print("foo......")
# time.sleep(2)
# @shoe_time
# def bar():
# print("bar......")
# time.sleep(3)
#
add(1,3,4,6,78) #
#3.000171661376953

带参数的装饰器

  装饰器还有更大的灵活性,例如带参数的装饰器:在上面的装饰器调用中,比如@shoe_time,该装饰器唯一的参数就是执行业务的函数。装饰器的语法允许我们在调用时,提供其它参数,比如@decorator(a)。这样,就为装饰器的编写和使用提供了更大的灵活性。

#带参数的装饰器

import time
def logger(flag=""):
def shoe_time(f):
def inner(*x,**y):
start = time.time()
f(*x,**y)
end = time.time()
print(end-start)
if flag == "true":
with open("日志记录", "a",encoding="utf8") as g:
g.write("值为: %s 时间为: %s\n"%(f(*x),(end-start)))
return inner
return shoe_time
@logger("true") #@show_time
def add(*a,**b):
Sum = 0
for i in a:
Sum += i
print(Sum)
time.sleep(3)
return Sum
@logger("abc")
def foo():
print("foo......")
time.sleep(2)
# @shoe_time
# def bar():
# print("bar......")
# time.sleep(3) add(1,3,4,6,78) #
#3.000171661376953
foo()

  @logger("true") 做了两件事:

(1)@ogger("true"):得到闭包函数show_time,里面保存环境变量flag

(2)@time   :add=show_time(add)

上面的logger是允许带参数的装饰器。它实际上是对原有装饰器的一个函数封装,并返回一个装饰器(一个含有参数的闭包函数)。当我 们使用@logger("true")调用的时候,Python能够发现这一层的封装,并把参数传递到装饰器的环境中。

 

python 学习笔记7(装饰器)的更多相关文章

  1. Python学习笔记:装饰器

    Python 装饰器的基本概念和应用 代码编写要遵循开放封闭原则,虽然在这个原则是用的面向对象开发,但是也适用于函数式编程,简单来说,它规定已经实现的功能代码不允许被修改,但可以被扩展,即: 封闭:已 ...

  2. Python学习笔记012——装饰器

    1 装饰器 1.1装饰器定义 在代码运行期间动态增加功能的方式,称之为“装饰器”(Decorator). 1.2 装饰器分类 装饰器:函数装饰器,类装饰器,函数的装饰器,类的装饰器 装饰器:函数装饰函 ...

  3. python学习笔记:装饰器2

    python的装饰器本质是函数,为了不改变装饰目标函数内部代码而增加额外功能而存在 一.一般装饰函数实例: import datetime def func_name(func):#定义一个装饰函数, ...

  4. python学习笔记(五):装饰器、生成器、内置函数、json

    一.装饰器 装饰器,这个器就是函数的意思,连起来,就是装饰函数,装饰器本身也是一个函数,它的作用是用来给其他函数添加新功能,比如说,我以前写了很多代码,系统已经上线了,但是性能比较不好,现在想把程序里 ...

  5. python学习笔记之装饰器、生成器、内置函数、json(五)

    一.装饰器 装饰器,这个器就是函数的意思,连起来,就是装饰函数,装饰器本身也是一个函数,它的作用是用来给其他函数添加新功能比如说,我以前写了很多代码,系统已经上线了,但是性能比较不好,现在想把程序里面 ...

  6. python学习笔记之装饰器、递归、算法(第四天)

    参考老师的博客: 金角:http://www.cnblogs.com/alex3714/articles/5161349.html 银角:http://www.cnblogs.com/wupeiqi/ ...

  7. Python学习笔记之装饰器原理

    def decorator(fn): def wrapper(): print("询价") fn() print("购买成功!") return wrapper ...

  8. python学习之day5,装饰器,生成器,迭代器,json,pickle

    1.装饰器 import os import time def auth(type): def timeer(func): def inner(*args,**kwargs): start = tim ...

  9. Python学习——迭代器&生成器&装饰器

    一.迭代器 迭代器是访问集合元素的一种方式.迭代器对象从集合的第一个元素开始访问,直到所有的元素被访问完结束.迭代器只能往前不会后退迭代器的一大优点是不要求事先准备好整个迭代过程中所有的元素.迭代器仅 ...

  10. 从零开始的Python学习Episode 11——装饰器

    装饰器 装饰器是用来处理其他函数的函数,主要作用是在不修改原有函数的情况下添加新的功能,装饰器的返回值也是一个函数对象. 简单的装饰器 import time def show_time(f): de ...

随机推荐

  1. iOS--二维码

    现在很多APP都涉及了二维码扫码功能,这个功能简单实用,很多情况下用户乐于使用,现在本文带来iOS7自带二维码扫码的教程,也包括扫条形码,足以满足简单的扫码要求,而且避免使用第三方的繁琐. 后期项目中 ...

  2. Change Git Default Editor in Windows

    On 32 bit Win OS: git config --global core.editor "'C:/Program Files/Notepad++/notepad++.exe' - ...

  3. jsoup简单的爬取网页数据

    /** * Project Name:JavaTest * File Name:BankOfChinaExchangeRate.java * Package Name:com.lee.javatest ...

  4. 什么才是正确的javascript数组检测方式

    前面的话 对于确定某个对象是不是数组,一直是数组的一个经典问题.本文专门将该问题择出来,介绍什么才是正确的javascript数组检测方式 typeof 首先,使用最常用的类型检测工具——typeof ...

  5. java中父类与子类, 不同的两个类中的因为构造函数由于递归调用导致栈溢出问题

    /* 对于类中对成员变量的初始化和代码块中的代码全部都挪到了构造函数中, 并且是按照java源文件的初始化顺序依次对成员变量进行初始化的,而原构造函数中的代码则移到了构造函数的最后执行 */ impo ...

  6. Docker 有什么优势?

    1.什么是容器? 依托与linux 内核功能的虚拟化技术 2. docker 是什么? 能够把应用程序自动部署到容器的开源引擎 3. docker 跟原有的工具有何区别? 传统的部署模式是:安装(包管 ...

  7. 哈夫曼树(三)之 Java详解

    前面分别通过C和C++实现了哈夫曼树,本章给出哈夫曼树的java版本. 目录 1. 哈夫曼树的介绍 2. 哈夫曼树的图文解析 3. 哈夫曼树的基本操作 4. 哈夫曼树的完整源码 转载请注明出处:htt ...

  8. 如何用UE(UltraEdit)删除重复行?--转

    原文地址:https://www.zhengjie.com/question/bb148773 使用UE(UltraEdit)的高级排序功能就可以删除掉所有的重复行. 操作步骤 1.文件—排序(R)— ...

  9. java io系列16之 PrintStream(打印输出流)详解

    本章介绍PrintStream以及 它与DataOutputStream的区别.我们先对PrintStream有个大致认识,然后再深入学习它的源码,最后通过示例加深对它的了解. 转载请注明出处:htt ...

  10. Azure REST API (1) 前言

    <Windows Azure Platform 系列文章目录> 一.服务运行时API简介 微软的Windows Azure服务总线提供了一整套REST风格的API,其中包括服务运行时API ...