BLOG

个人博客,记录学习与生活

装饰器、函数及类的调用

Published Feb. 20, 2020, 8 p.m. by kkk

最近系统地学习了一下装饰器,同时对调用加深了理解

装饰器|函数、类的调用

今天重看装饰器有感。

装饰器,可以看成一个语法糖,就是得一类操作的简化表示,但只使用这种简化表示而不了解其背后逻辑常常会陷入困惑。

函数装饰器

Java中,“everything is object”,由于python也是一门具有面向对象特点的语言,同样也具有一切皆对象的特点,同时对象也可以作为函数,既然是函数,就涉及调用。通过装饰器的例子来说明。

from functools import wraps
def outer(func):
    @warps(func)
    def inter():
        print('basic function')
    return inter

@outer
def f():
    print('extra function')

此时,函数f,通过装饰器以具备函数inter的功能,而操作@outer其实等同于

f = outer(f),通过f()则调用了函数。这是不带参数的装饰器,还有一种带参数的装饰器。

from functools import wraps
def outer(arg)
    def mid(func):
        @warps(func)
        def inter():
            print(arg)
            print('basic function')
        return inter
    return mid

@outer(arg='xxx')
def f():
    print('extra function')

这种写法,不仅实现是更函数增添功能的需求,同时实现了传参数给装饰函数的功能。但之前看的博客很多并没详细讲这种写法,这里的@outer(arg='xxx'),相当于f = outer(arg='xxx')(f),因为在outer定义中,定义了三层函数,前两层的返回值都是函数,所有可以进行两层函数调用,最后得到的f仍是一个函数,再进行函数调用f()就可以得到执行语句的输出。

类装饰器

今天看《python进阶》的时候,额外讲了类装饰器的用法,如下形式:

from functools import wraps
class Cal():
    def __init__(self, value):
        self.value = value
    def __call__(self, func):
        @wraps(func)
        def inter(*args, **kwargs):
            print(self.value)
            return func(*args, **kwargs)
        return inter
    pass

@Cal(value='xxx')
def f():
    print('extra funciton')

起初不太理解,再IPython下略加测试后才开始明白。由于定义了__call__方法,使得类变为可调用,再顺着上面的思路,可知,@Cal(value='xxx')实际相当于f=Cal(value='xxx')(f)。正是由于__call__方法的定义,使得实例类变得可以再次调用,而再次调用的表示则是__call__方法中的语句了。

在IPython中对一函数进行dir(func)的操作可以看到,函数内部都定义了定义__call__,使得func这一函数名变得可调用。


Share this post
< Pre: Django建立和运行 Pos: 感知机 >
2 comments
Similar posts
Add a new comment