简体   繁体   English

将实例变量传递给装饰器 class 内的包装器

[英]Pass instance variables to a wrapper inside a decorator class

In a previous question, someone informed me that I could use the getattr method to pass instance variables to a decorator function.在上一个问题中,有人告诉我,我可以使用getattr方法将实例变量传递给装饰器 function。 For example, here I should be able to pass c to some_wrapper.例如,这里我应该可以将c传递给 some_wrapper。

Here is the original question if anyone was interested.如果有人感兴趣,这是原始问题。 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):
        ...

Edit:编辑:

What the above allows me to do is pass c to some_wrapper when foo is passed into the decorator.上面允许我做的是在将 foo 传递给装饰器时将c传递给some_wrapper So if I have another method like:因此,如果我有另一种方法,例如:

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

self.c gets passed onto the other instance methods as well which is what I want. self.c被传递给其他实例方法,这就是我想要的。

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

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

However, I decided to go a different route and converted the function decorator into a class decorator.但是,我决定 go 使用不同的路线并将 function 装饰器转换为 class 装饰器。 ie: IE:

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

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

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

getattr doesn't work in the same way as I showed in the first example. getattr的工作方式与我在第一个示例中展示的方式不同。 My stab in the dark guess is that in my second example, the function is no longer passed as as argument anymore, so the self in getattr(self, 'c', None) no longer reference to the instance from the decorated function.我在黑暗中的猜测是,在我的第二个示例中,function 不再作为参数传递,因此 getattr( self getattr(self, 'c', None)中的 self 不再引用装饰的 function 中的实例。

Is there a work around this?有解决办法吗?

Works for me:为我工作:

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, *args, **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)

output: output:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM