首页 > 其他 > 详细

闭包,开放封闭原则和装饰器

时间:2020-07-21 00:39:52      阅读:115      评论:0      收藏:0      [点我收藏+]

闭包定义:

  • 闭包是嵌套在函数中的函数
  • 内层函数对外层函数非全局变量的使用(引用),就是闭包
def func1():
    li = []
    def func2(x):
        li.append(x)
        return li
    ruturn func2
f = func1()
print(f(100))   # [100]
print(f(100))   # [100, 100]
print(f(100))   # [100, 100, 100]
#li就是自由变量,并没有消失,但无法从函数外访问。

闭包的作用:

  • 被引用的非全局变量也称作自由变量,这个自由变量会与内层函数产生一个绑定关系。
    自由变量不会在内存中消失。
  • 保证数据安全。函数外无法访问自由变量

如何判断一个嵌套函数是不是闭包:

print(func.__code__.co_freevars)
# 只要返回值有自由变量那么就是闭包

开放封闭原则:

  • 开放:对代码的拓展开放,例如增加新功能
  • 封闭:对源码的修改封闭

装饰器:

  • 完全遵循开放封闭原则
  • 定义:
    • 在不改变原函数的代码以及其调用方式的前提下,为其增加新功能
    • 装饰器就是一个函数

例如:给函数添加一个功能用来测试函数的执行效率,计算效率的方法就是用函数执行完毕后的时间减去函数执行前的时间

import time
print(time.time()) # 显示此时此刻距离1970年1月1日0点0分0秒的秒数,也叫时间戳。
# 第一个版本
import time
def func1():
    time.sleep(1)  # 让程序停止1秒,模拟程序的执行耗时
    print(‘Hello,word!‘)

start_time = time.time()
func1()
end_time = time.time()
print(end_time - start_time)

# 实现了测试效率的功能,但代码写死,只能测试func1
# 第二个版本
import time
def func1():
    time.sleep(1)
    print(‘Hello,word!‘)

def timer(f):
    start_time = time.time()
    f()
    end_time = time.time()
    print(end_time - start_time)

timer(func1)
# 实现了功能并且可以测试其他函数,但改变了函数func的调用方式
# 第三个版本
import time
def func1():
    time.sleep(1)
    print(‘Hello,word!‘)

def timer(f):
    def inner():
        start_time = time.time()
        f()			# 装饰器的本质就是闭包,此时参数f是个自由变量
        end_time = time.time()
        print(end_time - start_time)
    return inner

func1 = timer(func1)	# 传进函数内的func1并不会改变
func1()		# 此时的func1()相当于inner()

# 在未改变原代码和调用方式的基础上,增加了功能,但多了一个赋值语句func1 = timer(func1)
# 若是调用其他函数则需要重复写代码,所以Python做了个优化:提出来语法糖的概念
# 第四个版本
import time

def timer(f):		# timer 就是个装饰器
    def inner():
        start_time = time.time()
        f()
        end_time = time.time()
        print(end_time - start_time)
    return inner

@timer	# 相当于 func1 = timer(func1) 写在函数之前
def func1():
    time.sleep(1)
    print(‘Hello,word!‘)
    return ‘in func1‘

print(func1())
# 此时func1实际上为inner,原func1的返回值是返回给原func1,并非返回给inner,所以值为None

# 	加语法糖才会调用timer
def func2():
    time.sleep(1)
    print("I‘m fine")
    return ‘in func1‘
func2()

# 此时迭代器基本实现,但会影响函数返回值,并且影响传参,还需要继续修改

# 版本六
import time

def timer(f):
    def inner():
        start_time = time.time()
        r = f()   # func1的调用实际在这一行,所以将func()的返回值赋值给r,将r返回给inner
        end_time = time.time()
        print(end_time - start_time)
        return r
    return inner

@timer
def func1():
    time.sleep(0.5)
    print(‘hello‘)
    return ‘in func1‘

print(func1())

# 此时func1实际上为inner,inner的返回值为r,也就是原func1的返回值
# 没有改变func1的调用方式,也没有改变func1的返回值,符合装饰器定义,接下来需要解决向func1传参

# 版本七
import time

def timer(f):
    def inner(*args,**kwargs): # 被装饰函数可能会接收各种参数,利用*的魔性用法可以接收所有参数
        start_time = time.time()
        r = f(*args,**args)   # *放在函数调用时表示打散
        end_time = time.time()
        print(end_time - start_time)
        return r
    return inner

@timer
def func1(n,a=‘18‘):
    time.sleep(0.5)
    print(f‘hello,{n},今年{a})
    return ‘in func1‘

print(func1(‘李白‘,n=‘33‘))
          
# 此时装饰器timer已全部完成,当需要测试某函数的执行效率时,则在被装饰函数定义前加上语法糖语句即可
# 最后标准格式的装饰器

def wrapper(f):
    def inner(*args,**args):
        ‘‘‘被装饰函数执行前添加的功能‘‘‘
        ret = f(*args,**args)
        ‘‘‘被装饰函数执行后添加的功能‘‘‘
        return ret
    return inner

闭包,开放封闭原则和装饰器

原文:https://www.cnblogs.com/ChiRou/p/13348143.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!