Fork me on GitHub

day 12

1. 闭包函数

闭包函数:将 闭包函数内部的变量 与 闭包函数内部的函数 打包在一起,以函数返回值的形式返回出来

def f1():
    def f2():
        print('from f2')
    return f2	# 将 函数 f2 的对象作为函数 f1 的返回值
f2 = f1()	# 当调用函数 f1 的时候,实际上在调用函数 f2 ,
f2()

由于局部作用域与全局作用域下相同名字的变量是没有任何关系的,所以在正常情况下,我们是不能直接在外部调用 函数 f2 ,实现打印功能的,运用闭包的思想,可以实现这种需求。

2. 装饰器

装饰器:给函数增加功能的函数

  • 装饰器本身也是一个函数,只是被用来装饰被装饰的函数
  • 使用装饰器函数时,不改变被装饰函数的源代码
  • 使用装饰器函数时,不改变被装饰函数的调用方式

2.1 装饰器模板

# 装饰器模板
def deco(func):
    def wrapper(*args, **kwargs):
        res = func(*args, **kwargs)
        return res

    return wrapper

2.2 装饰器语法糖

当一个函数具有装饰器时时可以使用装饰器语法进行快捷方便的调用

# 在被装饰函数正上方,并且是单独一行写上:@装饰器名
@deco
def f1():
    pass

2.3 三层装饰器

给二层装饰器函数传参。

# 三层装饰器
def sanceng(func3)
	def deco(func):
    	def wrapper(*args, **kwargs):
        	res = func(*args, **kwargs)
        	return res

    	return wrapper
    return deco

2.4 装饰器模板推导过程

2.4.1 不带参数和返回值的装饰器

# 模板
def deco(func):
    def wrapper():
    	func()    
    return wrapper

假设现在有一个函数 f1

import time
def f1():	# 函数对象 f1
    print('from f1')	# 函数功能
    time.sleep(1)
    
f1()	# 调用方式

如何在不改变函数的源代码及调用方式的前提下,实现计算 f1 功能耗费的时间

实现方法如下:

import time
def f1():	# 函数对象 f1
    '''被装饰函数'''
    print('from f1')	# 函数功能
    time.sleep(1)
    
# f1()	# 调用方式

def deco(func):	# 2. 这里的 func 实际上是真正的 f1 函数对象
    '''装饰器'''
    def wrapper():	# 3. 添加需要实现的功能
        start = time.time()
        func()		# 4. 相当于 f1(),调用函数 f1
        end = time.time()
        print(end - start)
    return wrapper	# 5. 将实现功能的函数对象 wrapper 和 结果 打包返回给装饰器函数 deco
f1 = deco(f1)	# 1. 将函数对象 f1 当作参数传给装饰器函数,会的到一个返回值对象使用 f1 接收,这里的 f1只是个普通的变量名,但是接收了函数对象 wrapper
f1() # 6. 实现了 f1 原来的功能,同时得到了运行程序的时间(这里的实际上是在调用装饰器函数里面的 wrapper ,已经不是原来的函数 f1 了)

2.4.2 带返回值的装饰器

# 模板
def deco(func):
    def wrapper():
    	res = func()    
    return wrapper

假设现在有一个函数 f1

import time
def f1():	# 函数对象 f1
    print('from f1')	# 函数功能
    time.sleep(1)
    return '返回值'
    
# f1()	# 调用方式

在不改变函数的源代码及调用方式的前提下,实现计算 f1 功能耗费的时间

实现方法如下:

import time
def f1():	# 函数对象 f1
    '''被装饰函数'''
    print('from f1')	# 函数功能
    time.sleep(1)
    return '返回值'
    
# f1()	# 调用方式

def deco(func):	# 2. 这里的 func 实际上是真正的 f1 函数对象
    '''装饰器'''
    def wrapper():	# 3. 添加需要实现的功能
        start = time.time()
        res = func()		# 4. 拿到真正 f1 函数的返回值
        end = time.time()
        print(end - start)
        
        return res	# 5. 将 f1 函数的返回值返回给 wrapper
    return wrapper	# 5. 将实现功能的函数对象 wrapper 和 返回值 打包返回给装饰器函数 deco
f1 = deco(f1)	# 1. 将函数对象 f1 当作参数传给装饰器函数,会的到一个返回值对象使用 f1 接收,这里的 f1只是个普通的变量名,但是接收了函数对象 wrapper
res = f1() # 6. 得到了 f1 的返回值,同时得到了运行程序的时间(这里的实际上是在调用装饰器函数里面的 wrapper ,已经不是原来的函数 f1 了)

2.4.3 带参数和返回值的装饰器

假设现在有一个函数 f1,比较两个数的大小,同样的添加计算程序运行的时间

def f1(x, y, z=10):
    '''被装饰函数'''
    if x > y:
        return x
    else:
        return z


f1(3, 5)  # 结果是 10
f1(5, 3)  # 结果是 5

在不改变函数的源代码及调用方式的前提下,实现计算 f1 功能耗费的时间

实现方法如下:

def f1(x, y, z=10):
    if x > y:
        time.sleep(1)
        return x
    else:
        time.sleep(2)
        return z


f1(3, 5)  # 结果是 10
f1(5, 3)  # 结果是 5


def deco(func):	# 2. 这里的 func 实际上是真正的 f1 函数对象
    '''装饰器'''
    def wrapper(*args, **kwargs):	# 3. 添加需要实现的功能,使用*args, **kwargs接收所有原函数可能传进来的值
        start = time.time()
        res = func(*args, **kwargs)		# 4. 使用*args, **kwargs打散所有可能传进来的参数
        end = time.time()
        print(end - start)
        
        return res	# 5. 将 f1 函数的返回值返回给 wrapper
    return wrapper	# 5. 将实现功能的函数对象 wrapper 和 返回值 打包返回给装饰器函数 deco
f1 = deco(f1)	# 1. 将函数对象 f1 当作参数传给装饰器函数,会的到一个返回值对象使用 f1 接收,这里的 f1只是个普通的变量名,但是接收了函数对象 wrapper
res = f1(5, 3) # 6. 得到了 f1 的返回值,同时得到了运行程序的时间(这里的实际上是在调用装饰器函数里面的 wrapper ,已经不是原来的函数 f1 了)
print(res)	
posted @ 2019-09-23 19:42  Yugaliii  阅读(113)  评论(0编辑  收藏  举报