Python装饰器类

9

我将尝试对带参数的class进行装饰,但无法使其工作:

以下是装饰器:

 def message(param1, param2):
   def get_message(func):
        func.__init__(param1,param2)

   return get_message

我想要放置装饰器的类

@message(param1="testing1", param2="testing2")
class SampleClass(object):
   def __init__(self):
     pass

但是这并没有起作用,当我运行它时会出现错误。有人知道问题在哪里吗?我正在尝试创建一个装饰器来初始化一些值。


装饰器在哪里返回要绑定到SampleClass的对象? - Ignacio Vazquez-Abrams
是的,那就是我需要帮助的地方。我不知道怎么做。 - IoT
你尝试从 get_message() 返回任何东西了吗? - Ignacio Vazquez-Abrams
func.__init__(param1,param2) 不可能发生,因为你只有 __init__(self) - Prajwal
1个回答

13

我很难理解你试图做什么。如果你想用带参数的装饰器来装饰一个类,可以像这样做。

2020-09-03:

感谢Maria-Ines Carrera指出原始代码实际上不能正确处理继承自其他类的类,user2357112支持Monica提出了一个可行的解决方案。

# function returning a decorator, takes arguments
def message(param1, param2):
    # this does the actual heavy lifting of decorating the class
    # it takes the original class, modifies it in place, and returns
    # the same class
    def wrapper(wrapped):
        the_init = wrapped.__init__

        def new_init(self):
            self.param1 = param1
            self.param2 = param2
            the_init(self)

        def get_message(self):
            return "message %s %s" % (self.param1, self.param2)

        wrapped.__init__ = new_init
        wrapped.get_message = get_message

        return wrapped
    return wrapper


class Pizza(object):
    def __init__(self):
        print "Pizza initialization"


@message("param1", "param2")
class Pizza2(Pizza):
    def __init__(self):
        print "Pizza2 initialization"
        super(Pizza2, self).__init__()

pizza_with_message = Pizza2()

# prints "message param1 param2"
print pizza_with_message.get_message()

这将打印以下内容:

Pizza2 initialization
Pizza initialization
message param1 param2

非常感谢,这正是我想要做的! - IoT
我认为这个不起作用 - 当尝试实例化装饰类时,它会导致无限递归。这是因为__init__调用其super()(已包装),该方法重新装饰自身,然后再次调用__init__,以此类推。我不确定在Python 2中是否有一种方法可以做到这一点 :( - mariaines
1
@Maria-InesCarrera 谢谢您指出这一点。我找到了复现您描述的错误的方法,并已经修复了答案。我需要更改第一个参数为super,这样它就可以跳过最外层的包装类。 - Greg Nisbet
@GregoryNisbet:但现在你跳过了包装类的__init__方法。此外,任何在包装类中使用2个参数的super的非__init__方法仍会遇到无限递归。创建一个子类并不是解决这个问题的好方法 - 直接修改原始类更有效。 - user2357112
1
@user2357112supportsMonica 感谢您的建议。我创建了一些新的函数并将它们添加到类中。看起来它很有效。 - Greg Nisbet

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接