【问题标题】:decorator inside class with arguments for function that accept arguments类内的装饰器,带有接受参数的函数的参数
【发布时间】:2017-05-26 05:33:14
【问题描述】:

我已经找到了在课堂上使用装饰器、使用 args 使用装饰器、使用 args 装饰函数的方法。但我不能让所有这些一起工作。我怎样才能做到这一点?

class Printer():
    """
    Print thing with my ESCPOS printer
    """
    def text(self, text):
        with open('/dev/usb/lp0', 'wb') as lp0:
            lp0.write(text.encode('cp437'))
            lp0.write(b'\n')
    def command(self, command):
        with open('/dev/usb/lp0', 'wb') as lp0:
            lp0.write(command)
            lp0.write(b'\n')
    def style(command_before, command_after):
        """
        Send a command before and a command after
        """
        def decorator(func):
            def wrapper(self, text):
                print(self)
                print(text)
                self.command(command_before)
                func(text)
                self.command(command_after)
            return wrapper
        return decorator
    @style((b'\x1D\x42\x31'), (b'\x1D\x42\x32')) #print white on black
    @style((b'\x1D\x21\x34'), (b'\x1D\y21\x00')) #print bigger
    def title(self, title_text):
        self.text(title_text)

那么我可以这样使用它:

p = Printer()
p.title('This is an awesome TITLE!!')

这给了我一个“TypeError: wrapper() missing 1 required positional argument: 'text'

但我只是没能得到它:/

【问题讨论】:

  • style() 应该是静态方法吗?你没有通过self
  • style 似乎只打算在类定义中使用;一旦定义了类,元类对它的作用似乎并不重要。
  • @chepner:啊。我想我明白了。 :) 因为style 在定义类时用作装饰器,所以它的行为类似于普通(未绑定)函数,而不是方法,所以它不需要self arg。这意味着我们可以将style 的定义移到class Printer(): 定义之外,它仍然可以正常工作。

标签: python decorator python-decorators


【解决方案1】:

func() 在你的装饰器中仍然是一个未绑定的函数。需要显式绑定或者显式传入self

# bind it to self
func.__get__(self)(text)

# or simply pass in self directly
func(self, text)

【讨论】:

    【解决方案2】:

    您对func 的调用需要阅读func(self, text)。原因是在这种情况下,func 还不是实例的绑定方法。

    在创建类时这是不可能的。没有可以将其绑定到的实例。所以你的包装函数中的func 只是一个普通函数,因此需要与你用

    定义的参数相同的参数
    def title(self, title_text)
        ...
    

    我把这个例子改成了这样

    class Printer():
        """
        Print thing with my ESCPOS printer
        """
        def text(self, text):
    #         with open('/dev/usb/lp0', 'wb') as lp0:
    #             lp0.write(text.encode('cp437'))
    #             lp0.write(b'\n')
            print('Text', text)
    
        def command(self, command):
    #         with open('/dev/usb/lp0', 'wb') as lp0:
    #             lp0.write(command)
    #             lp0.write(b'\n')
            print('Command', command)
    
        def style(command_before, command_after):
            """
            Send a command before and a command after
            """
            def decorator(func):
                def wrapper(self, text):
    #                 print(self)
    #                 print(text)
                    print('type of func', type(func))  # see that it is not bound
                    self.command(command_before)
                    func(self, text)  # <-- use (self, ...)
                    self.command(command_after)
                return wrapper
            return decorator
    
        @style((b'\x1D\x42\x31'), (b'\x1D\x42\x32')) #print white on black
        @style((b'\x1D\x21\x34'), (b'\x1D\y21\x00')) #print bigger
        def title(self, title_text):
            self.text(title_text)
    

    【讨论】:

    • @PM 2Ring 感谢您的提示。我应该仔细看看。
    • 正是我正在寻找的答案:) 以及我正在寻找的解释
    猜你喜欢
    • 2020-04-02
    • 1970-01-01
    • 2014-07-21
    • 1970-01-01
    • 1970-01-01
    • 2015-10-19
    • 1970-01-01
    • 1970-01-01
    • 2015-09-03
    相关资源
    最近更新 更多