装饰器

2.【理解】闭包的概念和基本使用

  • 闭包的作用:保证外层函数调用后,外层函数的变量不会销毁。

  • 闭包构成的条件:

      1. 函数嵌套的前提下

      2. 内层函数使用外层函数的变量

      3. 外层函数返回内层函数名

  • 基本使用:

    # 外层函数: 有一个参数叫num1
    def func_out(num1): # num1 = 100

    # 1.在函数嵌套的前提下
    # 内层函数:有一个参数叫num2
    def func_inner(num2):  # 使用外部函数变量的内部函数称为闭包。
        # 2.内部函数使用了外部函数的变量(num1)
        result = num1 + num2
        print(result)

    # 3.并且外部函数返回了内部函数,
    return func_inner


    if __name__ == '__main__':
    # 闭包对象
    f = func_out(100)  # f = func_inner

    f(100)
    f(200)

3.【理解】闭包的应用

  • 实现步骤说明

    • 定义外部函数接收不同的配置信息参数,参数是人名

    • 定义内部函数接收对话信息参数

    • 在内部函数里面把配置信息和对话信息进行拼接输出


# 需求: 根据配置信息使用闭包实现不同人的对话信息,例如对话:
#
# 张三: 到北京了吗?
# 李四: 已经到了,放心吧。


def config_name(name):  # name='张三' name='李四'

   # 闭包
   def say_info(info):
       print(name + ":" + info)

   return say_info

if __name__ == '__main__':

   zs = config_name("张三")      # zs = say_info

   zs("在吗?")
   zs("到深圳了吗?")

   ls = config_name("李四")      # ls = say_info
   ls('不在')
   ls('不和你玩')

   zs('我请客,吃鸡')
   ls('敲完代码先')

4.【了解】闭包中变量问题

  • 内层定义了和外层同名的变量

    重新在内层函数中定义了新的变量

  • 解决办法:nonlocal num1

    def func_out(num1):

    def func_inner(num2):
      # 声明使用外部函数变量num1
      nonlocal num1

      num1 = 10
      result = num1 + num2
      print(result)

    print(num1)
    func_inner(1)
    print(num1)

    return func_inner


    if __name__ == '__main__':
    f = func_out(1)

    f(2)
    f(3)

     

5.【理解】装饰器入门

  • 装饰器的作用:在不改变源代码和源代码调用方式的基础上,增加新的功能;

  • 装饰器使用:

    1) 待装饰函数=装饰器(待装饰函数)

    2)@装饰器

  • 写法:

    def func_out(fn):

    def inner():
      print("请先登录....")
      fn()
     
    return inner

    # 2.使用语法糖装饰
    @func_out
    def comment():
    print("发表评论....")


    # 1.使用装饰器装饰原函数
    # comment = func_out(comment)
    if __name__ == '__main__':
    comment()

6.【应用】装饰器的使用

  • 装饰器实现已有函数执行时间的统计


    # 使用装饰器统计函数的执行时间
    import time


    def get_time(fn):

    def inner():
        start = time.time()
        fn()
        end = time.time()
        print("执行函数花费时间: ", end - start)

    return inner


    @get_time
    def func1():
    for i in range(100000):
        print(i)


    if __name__ == '__main__':
    func1()

7.【应用】通用装饰器

  • 普通参数


    def func_out(fn):   # fn = func

    def inner(name):
        print("请先登录...")
        fn(name)        # func(name)

    return inner


    @func_out       # func=func_out(func) # func=inner
    def func(name):
    print(name, ":发表评论...")


    if __name__ == '__main__':
    func("小明")  # inner("小明")

  • 可变参数


    def func_out(fn):   # fn = func

    def inner(*args, **kwargs):
        print("请先登录...")
        fn(*args, **kwargs)        # func(name)

    return inner


    @func_out
    def func(*args, **kwargs):
    print(args)
    print(kwargs['name'], ":发表评论...")


    if __name__ == '__main__':
    func(1,2,3,4,name="小明")
  • 有返回值

    # 内层函数的结构应该和待装饰函数的结构一样


    def func_out(fn):   # fn = func

    def inner(name):    # name="小明"
        print("请先登录...")
        result = fn(name)        # result = func(name)
        return result

    return inner


    @func_out       # func=func_out(func)   # func=inner
    def func(name):
    print(name, ":发表评论...")
    return 100


    if __name__ == '__main__':
    value = func("小明")          # value = inner("小明")
    print("返回值:", value)
  • 通用装饰器

    • 作用:可以装饰不定长参数的函数和有返回值的函数。

    • 格式:


    # 通用装饰器
    def func_out(fn):

       def inner(*args, **kwargs):
           print("请先登录...")
           result = fn(*args, **kwargs)
           return result

       return inner
  • 使用:

    @func_out
    def func(*args, **kwargs):
       print(args)
       print(kwargs['name'], ":发表评论...")

       return 100


    @func_out
    def func2(name):
       print(name, ":发表评论...")


    @func_out
    def func3(name):
       print(name, ":发表评论...")
       return 100

8.【理解】多重装饰器

  • 多重装饰器:一个函数被多个装饰器装饰

  • 装饰原则:

    多个装饰器可以对函数进行多个功能的装饰,装饰顺序是由内到外的进行装饰,调用顺序正好相反。

9.【应用】带有参数的装饰器

  • 语法格式:

    # 带有参数的装饰器 (装饰器工厂函数)
    def logging(flag):

    def decroator(fn):
        def inner(n1, n2):
            if flag == "+":
                print("正在努力运行加法运行...")
            elif flag == "-":
                print("正在努力运行减法法运行...")
            result = fn(n1, n2)
            return result
        return inner

    # 返回装饰器
    return decroator
  • 使用方法:

  • @logging("+")       #解释器执行的顺序 1.logging("+") 2.@decroator
    def add(a, b):
    result = a + b
    return result


    @logging("-")       #解释器执行的顺序 1.logging("-") 2.@decroator
    def sub(a, b):
    result = a - b
    return result

10.【了解】类装饰器

  • 作用:使用类来实现闭包效果, 进行装饰

  • 类的书写:

    必须有两个方法

    1) __init__(self, fn)

    2)__call__(self, *args, **kwargs)


    # 类装饰器
    class func_out(object):

       def __init__(self, fn):     # fn = comment
           self.__fn = fn

       def __call__(self, *args, **kwargs):
           print("请先登录...")
           self.__fn()


    @func_out   # comment=func_out(comment) # comment是func_out类的对象.
    def comment():
       print("发表评论...")

原文地址:https://www.cnblogs.com/zhangwei112/p/13586793.html