两分钟学会Python装饰器

说装饰器之前先带大家了解一下闭包

1.闭包

闭包:简而言之就是将数据封装在一个包(区域)中,使用时再去里面取。(本质上 闭包是基于函数嵌套搞出来一个中特殊嵌套)

闭包应用场景1:封装数据防止污染全局,不需要全局使用,只需要在局部用到。

name = "shuai"

def f1():
    print(name, age)

def f2():
	print(name, age)

def f3():
	print(name, age)
    
def f4():
    pass
def func(age):
    name = "shuai"

    def f1():
        print(name, age)

    def f2():
        print(name, age)

    def f3():
        print(name, age)

    f1()
    f2()
    f3()

func(123)

闭包应用场景2:封装数据封到一个包里,使用时在取。

def task(arg):
    def inner():
        print(arg)
    return inner

v1 = task(11)
v2 = task(22)
v3 = task(33)
v1()
v2()
v3()
def task(arg):
    def inner():
        print(arg)
    return inner

inner_func_list = []
for val in [11,22,33]:
    inner_func_list.append( task(val) )
    
inner_func_list[0]() # 11
inner_func_list[1]() # 22
inner_func_list[2]() # 33
""" 基于多线程去下载视频 """
from concurrent.futures.thread import ThreadPoolExecutor

import requests


def download_video(url):
    res = requests.get(
        url=url,
        headers={
            "user-agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.88 Safari/537.36 FS"
        }
    )
    return res.content


def outer(file_name):
    def write_file(response):
        content = response.result()
        with open(file_name, mode='wb') as file_object:
            file_object.write(content)

    return write_file


POOL = ThreadPoolExecutor(10)

video_dict = [
    ("东北F4模仿秀.mp4", "https://aweme.snssdk.com/aweme/v1/playwm/?video_id=v0300f570000bvbmace0gvch7lo53oog"),
    ("卡特扣篮.mp4", "https://aweme.snssdk.com/aweme/v1/playwm/?video_id=v0200f3e0000bv52fpn5t6p007e34q1g"),
    ("罗斯mvp.mp4", "https://aweme.snssdk.com/aweme/v1/playwm/?video_id=v0200f240000buuer5aa4tij4gv6ajqg")
]
for item in video_dict:
    future = POOL.submit(download_video, url=item[1])
    future.add_done_callback(outer(item[0]))

POOL.shutdown()

2.装饰器

给你一个函数,在不修改函数源码的前提下,实现在函数执行前和执行后分别输入 "before" 和 "after"。

def func():
    print("我是func函数")
    value = (a,b,c) 
    return value
    
result = func()
print(result)

大部分的新手小白的实现思路都是在执行前和执行后直接加上print

def func():
    print("before")
    
    print("我是func函数")
    value = (a,b,c) 
    
    print("after")
    
    return value
    
result = func()

只有一个还好如果有一百个难道要手写一百个吗?接下来就用到装饰器

def outer(origin):
    def inner():
        print("before")
        origin()
        print("after")
    return inner

@outer # outer(func) 
def func():
    print("我是func函数")
    value = (1, 2, 3)

    return value


result = func()

原型就相当于

def outer(origin):
    def inner():
        print("before")
        origin()
        print("after")
    return inner

 
def func():
    print("我是func函数")
    value = (1, 2, 3)

    return value


result = outer(func)
result()

重要补充:functools

你会发现装饰器实际上就是将原函数更改为其他的函数,然后再此函数中再去调用原函数。

其实,一般情况下大家不用functools也可以实现装饰器的基本功能,但后期在项目开发时,不加functools会出错(内部会读取__name__,且__name__重名的话就报错),所以在此大家就要规范起来自己的写法。

import functools


def outer(origin):
    @functools.wraps(origin)
    def inner(*args, **kwargs):
        print("before")
        res = origin(*args, **kwargs)  # 执行原函数
        print("after")
        return res
    return inner


@outer
def func(*args, **kwargs):
    print("我是func函数")
    value = (1, 2, 3)
    return value


result = func(1, a=2)

总结

  1. 函数可以定义在全局、也可以定义另外一个函数中(函数的嵌套)

  2. 学会分析函数执行的步骤(内存中作用域的管理)

  3. 闭包,基于函数的嵌套,可以将数据封装到一个包中,以后再去调用。

  4. 装饰器

    • 实现原理:基于@语法和函数闭包,将原函数封装在闭包中,然后将函数赋值为一个新的函数(内层函数),执行函数时再在内层函数中执行闭包中的原函数。

    • 实现效果:可以在不改变原函数内部代码 和 调用方式的前提下,实现在函数执行和执行扩展功能。

    • 适用场景:多个函数系统统一在 执行前后自定义一些功能。

    • 装饰器示例

      import functools
      
      
      def auth(func):
          @functools.wraps(func)
          def inner(*args, **kwargs):
              """巴拉巴拉"""
              res = func(*args, **kwargs)  # 执行原函数
              return res
      
          return inner
      
      
      
      @auth
      def handler():
          pass
      
      handler()
      print(handler.__name__)  # handler 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值