嵌套类装饰器也是描述符类

Posted

技术标签:

【中文标题】嵌套类装饰器也是描述符类【英文标题】:Nested class decorators which are also descriptor classes 【发布时间】:2019-08-01 08:15:06 【问题描述】:

我有一种情况需要使用下面的嵌套装饰器,

class A(object):
    def __init__(self,v):
        print("A.init")
    @deco1
    @deco2
    def m(self, a):
        print("A.m")

装饰器的实现如下,

class deco1(object):
    def __init__(self, f):
        print("deco1.init")
        self.f = f
    def __call__(self, *args, **kwargs):
        print("deco1.call.before")
        r = self.f(*args, **kwargs)
        print("deco1.call.after")
        return r
    def __get__(self, o, c):
        print("deco1.get")
        return MethodType(self, o)

class deco2(object):
    def __init__(self, f):
        print("deco2.init")
        self.f = f
    def __call__(self, *args, **kwargs):
        print("deco2.call.before")
        r = self.f(*args, **kwargs)
        print("deco2.call.after")
        return r
    def __get__(self, o, c):
        print("deco2.get")
        return MethodType(self, o)

问题是没有调用 deco2 类的描述符方法,我需要调用它。 当我执行以下操作时,

aa = A(100)
aa.m(10)

实际

deco1.get
deco1.call.before
deco2.call.before
A.m
deco2.call.after
deco1.call.after

预期

deco1.get
deco1.call.before
deco2.get   #deco2.__get__ to be called
deco2.call.before
A.m
deco2.call.after
deco1.call.after

我需要单独的装饰器是有原因的。考虑到这一点,我怎么能做到这一点?另外,如果有人可以解释为什么不调用 deco2.get,那就太好了!谢谢。

使用 Python 3.7.x

【问题讨论】:

【参考方案1】:

deco2.get 在创建装饰的m 时被调用[一次]。

装饰

@deco1
@deco2
def m

可以改写为

m = deco1(deco2(m))

所以当计算 deco1 参数时,调用了 deco2.get。

【讨论】:

在我的示例中,deco2.get 从未被调用过。此外,在引用对象时调用装饰器方法(get 等)。即当我做 aa.m 时(m 是 deco1 的实例)。无论如何仍然没有回答我关于为什么没有调用 deco2.get 的问题(deco2 实例在 deco1 中被引用)

以上是关于嵌套类装饰器也是描述符类的主要内容,如果未能解决你的问题,请参考以下文章

装饰器

kotlin学习之类的修饰符与抽象类,嵌套类,内部类,匿名内部类

未找到 com.google.android.gms.vision.dynamite 的本地模块描述符类

在python中嵌套描述符/装饰器

结构体权限修饰符类简介

C#类详解