内部类的装饰器,带有接受参数的函数的参数

时间:2017-01-11 12:12:20

标签: python decorator python-decorators

我已经找到了在类中使用装饰器的方法,使用带有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()缺少1个必需的位置参数:'text'

但我得不到它:/

2 个答案:

答案 0 :(得分:3)

装饰器中的

func()仍然是一个未绑定的函数。您需要显式绑定它或明确传入self

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

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

答案 1 :(得分: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)