zoukankan      html  css  js  c++  java
  • jQuery火箭图标返回顶部代码

    本节主要内容:
    1. 通用装饰器回顾
    2. 函数的有用信息
    3. 带参数的装饰器
    4. 多个装饰器同时装饰一个函数
    一. 通用装饰器的回顾
    开闭原则: 对增加功能开放. 对修改代码封闭
    装饰器的作用: 在不改变原有代码的基础上给⼀个函数增加功能
    通用装饰器的写法:

    def wrapper(fn):
         def inner(*args,**kwargs):
         '''在目标函数之前做的事情'''
         ret = fn(*args,**kwargs)
         '''在目标函数执行之后做的事情'''
         return inner
    @wrapper
    def target_func():
          '''目标函数体'''
    target_func()

    执行过程:
    1. 程序从上向下, 当执行到@wrapper的时候. 把函数作为参数传递给wrapper函数. 得到
    inner函数. 重新赋值给target_func
    2. 当执行到target_func的时候. 我们实际上执行的是inner函数. inner函数会先执行目标
    函数之前的代码. 然后再执行你的目标函数. 执行完目标函数最后执行的是目标函数
    之后的代码
    二. 函数的有用信息
    1. 如何给函数添加注释

    def chi(food,drink):
          """
          这里是函数的注释,先写一下当前这个函数是干什么的,比如我这个函数就是一个吃
          :param food: 参数food是什么意思
          :param drink: 参数drink是什么意思
          :return: 返回的是什么东东
          """
          print(food,drink)
          return "very good"

    2.如何获取到函数的相关信息

    def chi(food,drink):
          """
          这里是函数的注释,先写一下当前这个函数是干什么的,比如我这个函数就是一个吃
          :param food: 参数food是什么东西
          :param drink: 参数drink是什么意思
          :return: 返回的是什么东东
          """
          print(food,drink)
          """
          这个可以获取到么
          """
          print(chi.__doc__)    # 获取函数的文档注释
          print(chi.__name__)    # 获取到函数名称
          return "very good"
    
    chi("吃嘛嘛香","我不想吃")
    print(chi.__doc__)
    print(chi.__name__)

      函数名.__name__可以查看函数的名字

      函数名.__doc__可以查看函数的文档注释

    接下来,我们来看一看被装饰器装饰之后的函数名:

    # 装饰器: 对传递进来的函数进行包装.可以在目标函数之前和之后添加任意的功能.
    def wrapper(func):
         def inner(*args,**kwargs):
               '''在执行目标函数之前要执行的内容'''
               ret = func(*args,**kwargs)
               '''在执行目标函数之后要执行的内容'''
               return ret
          return inner
    # @wrapper 相当于 target_func = wrapper(target_func) 语法糖
    @wrapper
    def target_func():
         print("我是目标函数")
    # 调用目标函数
    target_func()
    print(target_func.__name__)    # inner
    
    结果:
    inner

    我们虽然访问的是target_func函数. 但是实际上执行的是inner函数. 这样就会给下游的程
    序员带来困惑. 之前不是一直执行的是target_func么. 为什么突然换成了了inner. inner是个什
    么鬼?? 为了不让下游程序员有这样的困惑. 我们需要把函数名修改一下. 具体修改方案:

    from functools import wraps    #引入函数模块
    # 装饰器: 对传递进来的函数进行包装, 可以在目标函数之前和之后添加任意的功能.
    def wrapper(func):
         @wraps(func)    # 使用函数原来的名字
         def inner(*args,**kwargs):
               '''在执行目标函数之前要执行的内容'''
               ret = func(*args,**kwargs)
               '''在执行目标函数之后要执行的内容'''
               return ret
           return inner
    # @wrapper 相当于 target_func = wrapper(target_func) 语法糖
    @wrapper
    def target_func():
          print("我是目标函数")
    # 调用目标函数
    target_func()
    print(target_func.__name__)    # 不再是inner,而是target_func了
    @wrapper
    def new_target_func():
          print("我是另一个目标函数")
    new_target_func()
    print(new_target_func.__name__)

    PS: *args和**kwargs什么时候打散, 什么时候聚合
    1. 接收参数的时候是聚合, 参数声明
    2. 传递参数的时候是打散, 给函数传递实参

    def wrapper(func):
         @wraps(func)
         def inner(*args,**kwargs):    #这里是聚合
               '''在执行目标函数之前要执行的内容'''
               ret = func(*args,**kwargs)    # 这里是打散,这里的作用,其实就是为了保证我可以装饰所有函数而准备的
               '''在执行目标函数之后要执行的内容'''
               return ret
          return inner

    三. 装饰器传参
    现在来这样一个场景. 还是昨天的约.

    def wrapper(fn):
         @wrap(fn)
         def inner(*args,**kwargs):
              print("问问金老板啊,行情怎么样.")
              ret = fn(*args,**kwargs)
              print("艹,金老板骗我")
              return ret
         return inner
    
    @wrapper
    def yue():
         print("约一次又不会死")
    
    yue()

    那么现在如果查的很严. 怎么办呢? 打电话问金老板严不严. 那如果整体风声都不是那么
    紧呢. 是不是就不需要问金老板了. 所以. 我们需要一个开关来控制是否要询问金老板. 这时
    我们就需要给装饰器传递一个参数. 来通知装饰器要用怎么样的方式来装饰你的目标函数

    from functools import wraps
    
    def wrapper_out(flag):
         def wrapper(fn):
               @wraps(fn)
               def inner(*args,**kwargs):
                    if flag == True:    # 查的严啊, 先问问吧
                       print("问问金老板啊,行情怎么样.")
                       ret = fn(*args,**kwargs)
                       print("艹,金老板骗我")
                       return ret
                    else:    #查的不严,你慌什么
                        ret = fn(*args,**kwargs)
                        return ret
            return inner
        return wrapper
    @wrapper_out(False)    # 传递True和False来控制装饰器内部的运行效果
    def yue():
          print("约一次又不会死")
    
    yue()

    注意: 咱们之前的写法是@wrapper 其中wrapper是.一个函数. 那么也就是说. 如果我能让
    wrapper这里换成个函数就行了. wrapper(True)返回的结果是wrapper也是一个函数啊. 刚刚
    好和前面的@组合成一个@wrapper. 依然还是原来那个装饰器. 只不过这里套了3层. 但你要
    能看懂. 其实还是原来那个装饰器@wrapper
    执行步骤: 先执行wrapper(True) 然后再@返回值. 返回值恰好是wrapper. 结果就是
    @wrapper
    四. 多个装饰器装饰同一个函数
    先读一下这样一个代码.

    def wrapper1(fn):
          def inner(*args,**kwargs):
                print("111")
                ret = fn(*args,**kwargs)
                print("222")
                return ret
           return inner
    
    def wrapper2(fn):
          def inner(*args,**kwargs):
                print("333")
                ret = fn(*args,**kwargs)
                print("444")
                return ret
          return inner
    
    @wrapper2
    @wrapper1
    def eat():
          print("我想吃水果")
    eat()
    
    结果:
    333
    111
    我想吃水果
    222
    444

      执行顺序:首先@wrapper1装饰起来.然后获取到一个新函数是wrapper1中的inner.然后执行@wrapper2.这个时候.wrapper2装饰的就是wrapper1中的inner了. 所以.执行顺序就像: 第二层装饰器前(第一层装饰器前(目标)第一层装饰器后)第二层装饰器后.程序从左到右执行起来.就是我们看到的结果

  • 相关阅读:
    高盛、沃尔玛 题做出来还挂了的吐槽
    amazon师兄debrief
    到所有人家距离之和最短的中点 296. Best Meeting Point
    问问题没人回答的情况怎么办终于有解了
    找名人 277. Find the Celebrity
    数组生存游戏 289. Game of Life
    547. Number of Provinces 省份数量
    428. Serialize and Deserialize Nary Tree 序列化、反序列化n叉树
    alias别名简介和使用
    面试官:线程池执行过程中遇到异常会发生什么,怎样处理? Vincent
  • 原文地址:https://www.cnblogs.com/MayDayTime/p/9187141.html
Copyright © 2011-2022 走看看