2010-01-01 10 views
25

Warum kann decorator eine statische Methode oder eine Klassenmethode nicht dekorieren?Warum kann @decorator eine statische Methode oder eine Klassenmethode nicht dekorieren?

from decorator import decorator 

@decorator 
def print_function_name(function, *args): 
    print '%s was called.' % function.func_name 
    return function(*args) 

class My_class(object): 
    @print_function_name 
    @classmethod 
    def get_dir(cls): 
     return dir(cls) 

    @print_function_name 
    @staticmethod 
    def get_a(): 
     return 'a' 

Sowohl get_dir und get_a Ergebnis in AttributeError: <'classmethod' or 'staticmethod'>, object has no attribute '__name__'.

Warum beruht decorator auf dem Attribut __name__ anstelle des Attributs func_name? (Afaik alle Funktionen, einschließlich Klassenmethoden und staticmethods, haben das func_name Attribut.)

Edit: Ich benutze Python 2.6.

+1

Warum rufen Sie Funktion (* args) in der Dekorateur? Es ist Aufgabe, einfach eine Funktion zurückzugeben (in Ihrem Fall nicht modifiziert). – gahooa

+4

gahooa: weil das ist ein Weg 'Dekorator' (was er importiert, nicht das Sprachkonstrukt) funktioniert, siehe http://pypi.python.org/pypi/decorator. –

+0

@taldor Sie haben Dekorator-Modul in Py 2.6? – mykhal

Antwort

22

Es funktioniert, wenn @classmathod und @staticmethod sind die meisten Top-Dekorateure:

from decorator import decorator 

@decorator 
def print_function_name(function, *args): 
    print '%s was called.' % function.func_name 
    return function(*args) 

class My_class(object): 
    @classmethod 
    @print_function_name 
    def get_dir(cls): 
     return dir(cls) 
    @staticmethod 
    @print_function_name 
    def get_a(): 
     return 'a' 
+7

In der Regel 'classmethod' und 'staticmethod' wendet eine besondere Art von Magie an und muss zuletzt aufgerufen werden. –

3

Ist das, was Sie wollten?

def print_function_name(function): 
    def wrapper(*args): 
     print('%s was called.' % function.__name__) 
     return function(*args) 
    return wrapper 

class My_class(object): 
    @classmethod 
    @print_function_name 
    def get_dir(cls): 
     return dir(cls) 

    @staticmethod 
    @print_function_name 
    def get_a(): 
     return 'a' 
+2

Ich bin mir nicht sicher, ob Sie das bemerkt haben, aber das "Decorator" -Paket, das er benutzt, macht dasselbe wie das Konstrukt mit "Wrapper". Der einzige Unterschied zwischen Ihren Snippets besteht in der Reihenfolge, in der die Dekoratoren in My_class angewendet werden. Sie könnten das in der Antwort erklären, warum es die Dinge repariert. –

+0

Danke für eine Korrektur. Ich habe mit dem Problem in py3k gespielt, wo das Decorator-Modul fehlt. Ich meine meine Antwort, um die schnelle zu sein, und war sicher, dass jemand die bessere Antwort mit ausführlicher Erklärung posten wird – mykhal

+0

@ (Peter Hansen) .. aber es gibt kein Dekorator-Modul in Python 2.6 entweder – mykhal

37

classmethod und staticmethod return descriptor objects, nicht funktioniert. Die meisten Dekorierer sind nicht dafür ausgelegt, Deskriptoren zu akzeptieren.

Normalerweise müssen Sie dann und staticmethod zuletzt anwenden, wenn Sie mehrere Dekoratoren verwenden. Und da Dekoratoren in der Reihenfolge "von unten nach oben" angewendet werden, sollten normalerweise classmethod und staticmethod in Ihrer Quelle ganz oben stehen.

So:

class My_class(object): 
    @classmethod 
    @print_function_name 
    def get_dir(cls): 
     return dir(cls) 

    @staticmethod 
    @print_function_name 
    def get_a(): 
     return 'a' 
+7

+1 für die tatsächliche Beantwortung der Frage ("warum ...?"). –

Verwandte Themen