首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >没有类实例化调用的类方法的装饰器?

没有类实例化调用的类方法的装饰器?
EN

Stack Overflow用户
提问于 2020-01-02 15:25:38
回答 3查看 180关注 0票数 2

在下面的代码中,我为类Class方法创建了一个修饰器。我注意到,即使没有创建类实例,也会调用这个装饰器!而不用在类中调用这些方法!

对此有什么解释吗?

装潢师:

代码语言:javascript
复制
def deco(class_name):
    def inner_function(method):
        print("method is = {} and class is: {}".format(method.__name__,class_name.__name__))
        return method
    return inner_function

class_deco

代码语言:javascript
复制
class class_deco :
    def __init__(self):
        pass

类:

代码语言:javascript
复制
class Class :
    def __init__(self):
       pass

    @deco(class_deco)
    def f1(self):
        pass

    @deco(class_deco)
    def f2(self):
        pass

当我运行脚本时:

代码语言:javascript
复制
if __name__ == "__main__":
    pass

我得到了这个结果:

代码语言:javascript
复制
method is = f1 and class is: class_deco
method is = f2 and class is: class_deco
EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2020-01-02 15:31:22

装饰师只是用于以下内容的合成糖

代码语言:javascript
复制
@deco(class_deco)
def f1(self):
    pass

和-

代码语言:javascript
复制
f1 = deco(class_deco)(f1)

因此,当模块被导入时,这段代码就会运行,就像任何其他名称声明一样,f1名称将替换为上面所示的修饰f1。

票数 2
EN

Stack Overflow用户

发布于 2020-01-02 16:10:15

如前所述,@decorator语法只是语法糖,因此如下所示:

代码语言:javascript
复制
@somedecorator
def foo():
    pass

完全等价于

代码语言:javascript
复制
def foo():
    pass

foo = somedecorator(foo)

在这种情况下,您可以明确地调用装饰器函数:

代码语言:javascript
复制
@deco(class_deco)
def f1(self):
    pass

相当于:

代码语言:javascript
复制
def f1(self):
    pass

 _effective_decorator = deco(class_deco)

 f1 = _effective_decorator(f1)

这就是为什么您的inner_function确实在导入时被执行。

需要更多嵌套级别的装饰师需要更多的嵌套,因此从技术上讲,您的装饰师应该如下所示:

代码语言:javascript
复制
def deco(cls):
    def real_deco(func):
        def inner_function(*args, **kw):
            print("method is = {} and class is: {}".format(func.__name__,cls.__name__))
            return func(*args, **kw)
        return inner_function
    return real_deco
return inner_function

但是,如果重点是获取真正的所属的方法的类名,这仍然是不正确的--您应该从调用该方法的实例中获取该类,而不是尝试在装饰器调用中对其进行硬编码(因为在将装饰器应用于函数时,实际类并不存在)。因此,适当的实现应该如下所示:

代码语言:javascript
复制
def deco(func):
    # we're only supposed to use this on methods...
    def wrapper(self, *args, **kw):
        print("class {} - method {}".format(type(self).__name__, func.__name__))

    return wrapper


class Class:
    @deco
    def f1(self):
        pass

注:当然,这既不会处理类方法,也不会处理静态方法。

票数 2
EN

Stack Overflow用户

发布于 2020-01-02 16:12:44

下面是一个演示,展示了两种可能的装饰方法:

代码语言:javascript
复制
def Deco(*deco_params):
    print('In Deco', deco_params)
    def deco(func):
        print('In deco(func)')
        def inner(*args, **kwargs):
            print('In inner(*args, **kwargs)')
            return func(*args, **kwargs)
        return inner
    return deco

def deco(method):
    print('In deco(method)')
    def inner_function(*args, **kwargs):
        print("method is = {} called".format(method.__name__))
        return method(*args, **kwargs)
    return inner_function


class Class :
    def __init__(self):
       pass

    @deco
    def f1(self):
        pass

    @Deco(42)
    def f2(self):
        pass

if __name__ == "__main__":
    print('Now in Main')
    c = Class()
    c.f1()
    c.f2()

输出:

代码语言:javascript
复制
In deco(method)
In Deco (42,)
In deco(func)
Now in Main
method is = f1 called
In inner(*args, **kwargs)
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/59565816

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档