闭包和装饰器(语法糖)

闭包

  • 函数嵌套(外部函数中定义了一个内部函数)
  • 外部函数返回了内部函数
  • 内部函数使用了外部函数的变量(包括外部函数的参数)
def func_outer():
    # 定义一个全局变量 count,来记录 sub 函数的调用次数
    count = 0

    def sub(a, b):
        """计算两个数之差"""
        nonlocal count
        count += 1 # count = count + 1
        print(f'第{count}次调用该函数')
        return a - b

    return sub

# 注意:这里调用外部函数,是为了拿到内部函数对象
func = func_outer()
print(func)
func(1, 2)
func(2, 3)
func(3, 5)

装饰器(语法糖)

import time

# 装饰器函数
def get_time(func):
    def wrapper(num):
        # todo: wrapper函数的参数 func函数的参数
        s1 = time.time()
        # todo:调用原始函数,调用时可以先获取原始函数的返回值
        result = func(num)
        s2 = time.time()
        print('执行时间:', s2 - s1)
        # todo:将原始函数的返回值再返回
        return result

    return wrapper

@get_time
def func1(num):
    _sum = 0
    for i in range(1, num+1):
        _sum += i
    return _sum

res = func1(100)
print(res)

通用装饰器

# 装饰器通用写法
import time
def get_time(func):
    def wrapper(*args,**kwargs):
        # 加强代码
        s = time.time()

        # 调用原始函数
        result = func(*args,**kwargs)

        # 加强代码
        e = time.time()
        print(f"运行耗时{e - s}")

        return result
    return wrapper

@get_time
def fun1(m,n):
    _sum = 0
    for i in range(m,n):
        _sum += i
    return _sum

_sum = fun1(1, 10000000)
print(_sum,type(_sum))

带参装饰器

"""
@装饰器(参数)
本质:带参装饰器的本质,是在普通的装饰器的外面,又包了一层函数
"""
import time

"""普通装饰器 2层函数嵌套,无需最外层的函数包裹
装饰器带参数,就在2层基础上,再加一层,专门接收装饰器的参数
"""
def func_outer(float_decimals):
    """接收装饰器的参数"""
    """返回 下一层函数(名字)"""
    def get_time(func):
        """接收被装饰的函数"""
        """返回 内层函数(名字)"""
        def wrapper(*args, **kwargs):
            """接收被装饰函数的参数"""
            """对被装饰的函数额外加功能,会用到外层函数的参数"""
            """运行被装饰的函数"""
            """返回 被装饰函数运行的结果"""
            s1 = time.time()
            result = func(*args, **kwargs)
            s2 = time.time()
            # 控制小数的位数
            ret = round(s2-s1, float_decimals)
            print(f'函数的执行时间为:{ret}秒')
            return result
        return wrapper
    return get_time

@func_outer(float_decimals=3) # 控制输出的小数位数
def func1():
    """func1函数无参数,也无返回值"""
    _sum = 0
    for i in range(1000000):
        _sum += i
    return _sum

print(func1())

总结:
第一层的参数:用来接收装饰器自己需要用到的参数.
第二层的参数:用来接收被装饰/改造的方法的内存地址.
第三层的参数:用来接收被装饰/改造的方法的参数.

你可能感兴趣的:(python)