2017-01-11 1 views
1

J'ai trouvé moyen d'avoir un décorateur en classe, d'avoir un décorateur avec des arguments, de décorer la fonction avec des arguments. Mais je ne peux pas tout faire fonctionner ensemble. Comment puis-je faire ce travail?décorateur en classe avec des arguments pour la fonction qui accepte les arguments

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) 

alors je pourrais l'utiliser de cette façon:

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

Cela me donne un "TypeError: emballage() manquant 1 nécessaire argument de position: 'texte'"

Mais je juste échouer à l'obtenir:/

+1

est 'le style()' censé être une méthode statique? Vous ne passez pas en 'self' –

+0

' style' semble seulement destiné à être utilisé dans la définition de la classe; ce que fait la métaclasse une fois la classe définie ne semble pas avoir d'importance. – chepner

+1

@chepner: Ah. Je pense que je comprends. :) Parce que 'style' est utilisé comme décorateur pendant la définition de la classe, il se comporte comme une fonction normale (non liée), pas comme une méthode, donc il ne prend pas un argument' self'. Et cela signifie que nous pourrions déplacer la définition de 'style' en dehors de la classe' Printer(): 'definition & cela fonctionnera correctement. –

Répondre

2

Votre appel à func a besoin de lire func(self, text). La raison en est que dans ce cas func n'est pas encore une méthode liée à une instance.

Ce n'est pas possible au moment de la création de la classe. Il n'y a aucune instance à laquelle vous pourriez vous lier. Donc func dans votre fonction d'emballage est juste une fonction simple et doit donc les mêmes arguments que vous l'avez défini avec

def title(self, title_text) 
    ... 

J'ai changé l'exemple comme celui-ci

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) 
+0

@PM 2Ring Merci pour l'indice. J'aurais dû regarder plus attentivement. – jhp

+0

Exactement la réponse que je cherchais :) et l'explication que je recherchais – Spoutnik16

3

func() dans votre décorateur est encore une fonction non liée. Vous devez lier explicitement ou passer self explicitement:

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

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