微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

将实例变量传递给装饰器类中的包装器

如何解决将实例变量传递给装饰器类中的包装器

在上一个问题中,有人告诉我可以使用 getattr 方法将实例变量传递给装饰器函数。例如,在这里我应该能够将 c 传递给 some_wrapper。

如果有人感兴趣,这是原始问题。 Passing instance variables to a decorator

import functools 

def some_func(
   a = False,b = None
):
      def some_decorator(func):
          @functools.wraps(func)
          def some_wrapper(self,*args,**kwargs):
              c = getattr(self,'c',None)

              ...


class MyClass:
    def __init__(self,arg,c=None):
        self.arg = arg
        self.c = c

    @some_func(a=True)    
    def foo(self,x,y):
        ...

编辑:

当 foo 被传递到装饰器时,上面允许我做的是将 c 传递给 some_wrapper。因此,如果我有另一种方法,例如:

    @some_func(a=True)    
    def bar(self,alpha,beta):
        ...

self.c 也被传递给其他实例方法,这正是我想要的。

instance = MyClass(arg,c = 'Hi')

instance.foo(arg,blarg)
instance.bar(alpha,beta)

然而,我决定走不同的路线,将函数装饰器转换为类装饰器。即:

class SomeClass():
    def __init__(self,**kwargs):
        self.a = None
        self.b = None
       
    def __get__(self,obj,objtype):
        import functools
        return functools.partial(self.__call__,obj)
                

    def __call__(self,**kwargs):
        def some_wrapper(*args,**kwargs):
            c = getattr(self,None)

        ...
        self.func = args[0]
        return some_wrapper

getattr 的工作方式与我在第一个示例中展示的方式不同。我暗中猜测的是,在我的第二个示例中,该函数不再作为参数传递,因此 self 中的 getattr(self,None) 不再引用装饰函数中的实例。>

有办法解决这个问题吗?

解决方法

对我有用:

import functools


def some_func(a=False,b=None):
    def some_decorator(func):
        @functools.wraps(func)
        def some_wrapper(self: "MyClass",*args,**kwargs):
            kwargs.pop("y")
            c = self.c
            return func(self,**kwargs,y=c)
        return some_wrapper
    return some_decorator


class MyClass:
    def __init__(self,arg,c=None):
        self.arg = arg
        self.c = c

    @some_func(a=True)
    def foo(self,x,y):
        print(f"foo x={x} y={y}")


no_c = MyClass("arg")
no_c.foo(x=3,y=4)
yes_c = MyClass("blarg",c="I do")
yes_c.foo(x=3,y=4)

输出:

foo x=3 y=None
foo x=3 y=I do

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。