【问题标题】:Python decorating classPython装饰类
【发布时间】:2017-04-16 22:18:53
【问题描述】:

我正在尝试用参数装饰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的对象?
  • 是的,这就是我需要帮助的地方。我不知道该怎么做。
  • 你有没有尝试从get_message()返回一些东西?
  • func.__init__(param1,param2) 这不可能发生,因为你只有__init__(self)

标签: python python-decorators


【解决方案1】:

我无法弄清楚您要做什么。如果你想用一个带参数的装饰器来装饰一个类,一种方法是这样的。

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

【讨论】:

  • 非常感谢,这正是我想做的!
  • 我认为这行不通——在尝试实例化装饰类时会导致无限递归。那是因为__init__ 调用它的 super() (包装),它重新装饰自己,它再次调用__init__ 等等。我不确定在 python 2 中有没有办法做到这一点:(
  • @Maria-InesCarrera 感谢您指出这一点。我想出了如何重现您描述的错误并修复了答案。我需要将第一个参数更改为super,以便它跳过包装类的最外层。
  • @GregoryNisbet:但是现在您正在跳过包装类的 __init__ 方法。此外,任何在包装类中使用 2 参数 super 的非 __init__ 方法仍然会遇到无限递归。创建一个子类并不是解决这个问题的好方法 - 就地修改原始类效果更好。
  • @user2357112supportsMonica 感谢您的建议。我在旁边创建了一些新功能,然后将它们装订到课堂上。它似乎有效。
猜你喜欢
  • 2011-04-28
  • 2021-07-16
  • 2023-03-03
  • 2014-02-16
  • 2015-08-21
  • 1970-01-01
  • 2010-12-19
  • 2012-02-09
  • 2019-09-20
相关资源
最近更新 更多