" name="sm-site-verification"/>
侧边栏壁纸
博主头像
PySuper博主等级

千里之行,始于足下

  • 累计撰写 203 篇文章
  • 累计创建 14 个标签
  • 累计收到 1 条评论

目 录CONTENT

文章目录

装饰器封装功能函数 | @Func()

PySuper
2020-04-04 / 0 评论 / 0 点赞 / 8 阅读 / 6014 字
温馨提示:
所有牛逼的人都有一段苦逼的岁月。 但是你只要像SB一样去坚持,终将牛逼!!! ✊✊✊

装饰器

在不改动源代码的情况下,给函数添加一个额外的功能

def fun():
    def inner():
        print("额外的功能")
    return inner

@fun
def game():
    print("这是函数原有的功能")

执行顺序

多个装饰器时:从下向上执行

def fun_1(fun):
    def func(*args, **kwargs):
        print("--我在函数内层--1, 额外的功能-1")
        fun()

    print("--我在外层")
    return func


def fun_2(fun):
    def func(*args, **kwargs):
        print("--我是函数内层——2, 额外的功能--2")
        fun()

    print("--我在第二个装饰器外层")
    return func


@fun_1
@fun_2
def func_for():
    print("--我是第一个函数")


func_for()
# 我在第二个装饰器外层
# 我在外层
# 我在函数内层--1, 额外的功能-1
# 我是函数内层——2, 额外的功能--2
# 我是第一个函数

携带参数

当装饰器携带参数时,参数怎么用,怎么传,这里分不同情况

无参数的函数

from time import ctime


def time_fun(func):
    def wrapped_func():
        print("%s called at %s" % (func.__name__, ctime()))
        func()

    return wrapped_func


@time_fun
def foo():
    print("I am foo")


foo()
# foo called at Sat Apr  4 17:50:03 2020
# I am foo

被装饰的函数有参数

from time import ctime


def time_fun(func):
    def wrapped_func(a, b):
        print("%s called at %s" % (func.__name__, ctime()))
        print(a, b)
        func(a, b)

    return wrapped_func


@time_fun
def foo(a, b):
    print(a + b)


foo(3, 5)
# foo called at Sat Apr  4 17:50:59 2020
# 3 5
# 8

被装饰的函数有不定长参数

from time import ctime, sleep


def time_fun(func):
    def wrapped_func(*args, **kwargs):
        print("%s called at %s" % (func.__name__, ctime()))
        func(*args, **kwargs)

    return wrapped_func


@time_fun
def foo(a, b, c):
    print(a + b + c)


foo(3, 5, 7)
sleep(1)
foo(2, 4, 9)
# foo called at Sat Apr  4 17:53:31 2020
# 15
# foo called at Sat Apr  4 17:53:32 2020
# 15

装饰器中的return

from time import ctime, sleep


def time_fun(func):
    def wrapped_func():
        print("%s called at %s" % (func.__name__, ctime()))
        func()

    return wrapped_func


@time_fun
def foo():
    print("I am foo")


@time_fun
def getInfo():
    return '----hahah---'


foo()
sleep(2)
foo()

print(getInfo())
# foo called at Sat Apr  4 17:54:04 2020
# I am foo
# foo called at Sat Apr  4 17:54:06 2020
# I am foo
# getInfo called at Sat Apr  4 17:54:06 2020
# None

装饰器带参数,在原有装饰器的基础上,设置外部变量

from time import ctime, sleep


def time_fun_arg(pre="hello"):
    def time_fun(func):
        def wrapped_func():
            print("%s called at %s %s" % (func.__name__, ctime(), pre))
            return func()

        return wrapped_func

    return time_fun


# 下面的装饰过程
# 1. 调用time_fun_arg("spider")
# 2. 将步骤1得到的返回值,即time_fun返回, 然后time_fun(foo)
# 3. 将time_fun(foo)的结果返回,即wrapped_func
# 4. 让foo = wrapped_fun,即foo现在指向wrapped_func
@time_fun_arg("spider")
def foo():
    print("I am foo")


@time_fun_arg("python")
def too():
    print("I am too")


foo()
sleep(1)
foo()

too()
sleep(1)
too()
# foo called at Sat Apr  4 18:04:00 2020 itcast
# I am foo
# foo called at Sat Apr  4 18:04:02 2020 itcast
# I am foo
# too called at Sat Apr  4 18:04:02 2020 python
# I am too
# too called at Sat Apr  4 18:04:04 2020 python
# I am too

类装饰器

class Test(object):
    def __init__(self, func):
        print("---初始化---")
        print("func name is %s" % func.__name__)
        self.__func = func

    def __call__(self):
        print("---装饰器中的功能---")
        self.__func()


@Test
def test():
    print("----test---")
# ---初始化---
# func name is test
# ---装饰器中的功能---
# ----test---
  • 说明:
    • 当用Test来装作装饰器对test函数进行装饰的时候,首先会创建Test的实例对象
      • 并且会把test这个函数名当做参数传递到__init__方法中
      • 即在__init__方法中的属性__func指向了test指向的函数
    • test指向了用Test创建出来的实例对象
    • 当在使用test()进行调用时,就相当于让这个对象(),因此会调用这个对象的__call__方法
    • 为了能够在__call__方法中调用原来test指向的函数体,所以在__init__方法中就需要一个实例属性来保存这个函数体的引用
    • 所以才有了self.__func = func这句代码,从而在调用__call__方法中能够调用到test之前的函数体
0
  1. 支付宝打赏

    qrcode alipay
  2. 微信打赏

    qrcode weixin

评论区