Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/310.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 装饰方法导致方法传入对象_Python - Fatal编程技术网

Python 装饰方法导致方法传入对象

Python 装饰方法导致方法传入对象,python,Python,问题描述 我想使用装饰器来定义类方法,但这需要我在不需要提供“self”对象时手动提供该对象 def func_wrapper(func): def call_func(self): print(self.a) func() return call_func def func(): print('hello') class test: def __init__(self, func): self.a = 0

问题描述 我想使用装饰器来定义类方法,但这需要我在不需要提供“self”对象时手动提供该对象

def func_wrapper(func): 
    def call_func(self):
        print(self.a)
        func()
    return call_func
def func():
    print('hello')

class test:
    def __init__(self, func):
        self.a = 0
        self.call_func = func_wrapper(func)

mytest = test(func)
#mytest.call_func() #why does this not work? 
mytest.call_func(mytest) #this works 
我希望能够调用mytest.call_func(),但这不起作用,可能是因为call_func绑定到func_包装,而不是mytest。如果我手动传入对象,例如mytest.call_func(mytest),这将起作用,但我不希望必须手动传入对象-如果继承了测试类并编写了自己的call_func方法,这将创建不一致的调用签名,因为这样该方法将正确绑定到该类

解决方案尝试

def func_wrapper2(func, obj): 
    def call_func():
        print(obj.a)
        func()
    return call_func
class test:
    def __init__(self, func):
        self.a = 0
        self.call_func = func_wrapper2(func, self)
这是一个让我可以测试的解决方案。根据需要调用_func(),但这里的func_包装器不是真正的装饰器,因为它也需要在对象中传递

在网上我发现了这个博客,它讨论了这个问题,并建议在嵌套类或帮助类中定义decorator。然而,他们的解决方案似乎不起作用,我通过传递错误数量的输入而得到类型错误

class test2: 
    class test2helper: 
        @classmethod
        def func_wrapper(func):
            print(self.a)
            func()
    def __init__(self):
        self.a = 0
    @test2helper.func_wrapper
    def call_func(self):
        print('hello')

那么,在类方法中使用decorator的正确方法是什么呢?这样做的每一种方式似乎都会导致不同的自我处理问题。除非有更好的方法,否则我将使用func_包装器2设计

您缺少一个级别:

class test2: 
    class test2helper: 
        @classmethod
        def decorator(cls, func):  # this must return a function!
            def func_wrapper(self):  # ... namely this one, the "wrapper"
                print(self.a)  # ... where you have access to the instance
                func(self)  # ... upon which the method is called
            return func_wrapper

    def __init__(self):
        self.a = 0

    @test2helper.decorator
    def call_func(self):
        print('hello')

>>> t = test2()
>>> t.call_func()
0
hello
或者,如果要在不使用嵌套类的情况下继续先前的尝试:

def decorator(func):  # you are decorating an unbound function!
    def func_wrapper(obj): 
        print(obj.a)
        func(obj)  # which has to be passed all the arguments
    return func_wrapper

class test:
    def __init__(self):
        self.a = 0

    @decorator
    def call_func(self):
        print('hello')

您缺少一个级别:

class test2: 
    class test2helper: 
        @classmethod
        def decorator(cls, func):  # this must return a function!
            def func_wrapper(self):  # ... namely this one, the "wrapper"
                print(self.a)  # ... where you have access to the instance
                func(self)  # ... upon which the method is called
            return func_wrapper

    def __init__(self):
        self.a = 0

    @test2helper.decorator
    def call_func(self):
        print('hello')

>>> t = test2()
>>> t.call_func()
0
hello
或者,如果要在不使用嵌套类的情况下继续先前的尝试:

def decorator(func):  # you are decorating an unbound function!
    def func_wrapper(obj): 
        print(obj.a)
        func(obj)  # which has to be passed all the arguments
    return func_wrapper

class test:
    def __init__(self):
        self.a = 0

    @decorator
    def call_func(self):
        print('hello')
您可以定义一个装饰器来执行您想要的操作:

def class_decorator(cls):
    def call_func(self):
        print(self.a)
        return func()

    setattr(cls, 'call_func', call_func)
    return cls

def func():
    print('hello')


@class_decorator
class Test:
    def __init__(self, func):
        self.a = 0


mytest = Test(func)
mytest.call_func()  # This now works.
输出:

0
你好
您可以定义一个装饰器来执行您想要的操作:

def class_decorator(cls):
    def call_func(self):
        print(self.a)
        return func()

    setattr(cls, 'call_func', call_func)
    return cls

def func():
    print('hello')


@class_decorator
class Test:
    def __init__(self, func):
        self.a = 0


mytest = Test(func)
mytest.call_func()  # This now works.
输出:

0
你好

在您的第一个代码段中,
self.call\u func=func\u wrapper(func)。\uu获取(self,test)
不要将方法分配给实例,在类级别执行。在您的第一个代码段中,
self.call\u func=func\u wrapper(func)。\uu获取(self,test)
不要将方法分配给实例,在类级别执行。