Python 三程三器的那些事

  • 2020 年 3 月 10 日
  • 筆記

装饰器

1、什么是装饰器

  • 装饰器本质是函数,用来给其他函数添加新的功能
  • 特点:不修改调用方式、不修改源代码

2、装饰器的作用

  • 装饰器作用:本质是函数(装饰其他函数)就是为其他函数添加其他功能
  • 装饰器必须准寻得原则
    • 不能修改被装饰函数的源代码、不能修改被装饰函数的调用方式
  • 实现装饰器知识储备
    • 函数即“变量”
    • 高阶函数
    • 嵌套函数 高阶函数+潜逃函数=》装饰器

3、使用高阶函数模仿装饰器功能

    1.定义:把一个函数名当做实参传给另一个函数
    2.返回值中包含函数名
    3.下面使用高阶函数虽然可以实现装饰器的一些功能,但是违反了装饰器不能改变调用方式的原则,
         以前使用bar()现在将调用方式改编成了test1(bar)就是将bar的函数名当做变量传给了test1()

#! /usr/bin/env python  # -*- coding: utf-8 -*-  import time    def timer(func):      start_time = time.time()      func()      print '函数执行时间为', time.time() - start_time    def test():      print '开始执行test'      time.sleep(3)      print 'test执行结束'      timer(test)  '''  开始执行test  test执行结束  函数执行时间为 3.00332999229  '''

改变了调用方式

    4.高阶函数——不修改高阶函数的调用方式增加新的功能(但是无法传参数)
    注:bar = test2(bar) 等价于:@timer重新将函数名bar赋值,将原函数bar的内存地址当做实参传递该函数test2(),再将test2()赋值给bar

import time  def bar():      time.sleep(3)      print("in the bar")  def test2(func):      print(func)      return func  bar = test2(bar)  bar()

不改变调用方式

    5.嵌套函数
      嵌套函数:在一个函数中嵌套另一个函数,并在函数内部调用

def foo():      print("in the foo")      def bar():          print("in the bar")      bar()  foo()

嵌套函数

4、能够适应90%的业务需求

  • 在装饰器中 @timer等价于 test1=timer(test1)
  • 在timer()函数中返回值是return deco
  • 所以timer(test1)作用是将函数test1内存地址当做参数传递给timer()
  • timer() 函数最后将运行后的函数deco内存地址作为返回值返回
  • test1=timer(test1)作用就是将将deco函数内存地址赋值给test1,所以最后运行test1()就相当于运行deco()
  • 所以最后调用时给test2()传入参数就相当于给deco传入参数
import time  def timer(func):   #timer(test1)  func=test1      def deco(*args,**kwargs):          start_time = time.time()          func(*args,**kwargs)      #run test1          stop_time = time.time()          print("running time is %s"%(stop_time-start_time))      return deco  @timer     # test1=timer(test1)  def test1():      time.sleep(3)      print("in the test1")  @timer  def test2(name):      print("in the test2",name)  test1()  test2("tom")

装饰器1

5、对特定网页进行身份验证

import time  user,passwd = 'aaa','123'  def auth(func):      def wrapper(*args,**kwargs):          username = input("Username:").strip()          password = input("Password:").strip()          if user == username and password == passwd:              print("User has passed authentication")              res = func(*args,**kwargs)   #这里执行func()相当于执行调用的函数如home()              return res          #为了获得home()函数返回值,可以将执行结果赋值给res然后返回print(home())结果是"from home"而不是"None"了          else:              exit("Invalid username or password")      return wrapper  def index():      print("welcome to index page")  @auth  def home():      print("welcome to home page")      return "from home"  @auth  def bbs():      print("welcome to bbs page")  index()  print(home())   #在这里调用home()相当于调用wrapper()  bbs()

装饰器2

6、实现对不同网页不同方式的身份认证

  • @auth(auth_type=“local”)代码作用
  • 在上面的代码中使用@auth相当于先将home函数的内存地址当做变量传入auth()函数,执行结果后home()相当于wrapper()
  • 而在这里验证的时候犹豫@auth(auth_type=”local”)中有()括号,那么就相当于将执行auth()函数而且是将auth_type=“local当做参数传入到auth()函数执行
  • 所以outer_wrapper函数也会执行,outer_wrapper函数的执行结果返回的就是wrapper()函数的内存地址
  • 所以最终结果同样是执行home()函数就相当于执行wrapper函数
  • 但是有所不同的是着这个版本中我们可以在外层的auth函数中传入新的参数帮组我们根据需求判断 
import time  user,passwd = 'aaa','123'  def auth(auth_type):      print("auth func:",auth_type)      def outer_wrapper(func):          def wrapper(*args, **kwargs):              print("wrapper func args:", *args, **kwargs)              if auth_type == "local":                  username = input("Username:").strip()                  password = input("Password:").strip()                  if user == username and passwd == password:                      print("