Je veux écrire un décorateur qui agit différemment selon qu'elle est appliquée à une fonction ou à une méthode.
def some_decorator(func): if the_magic_happens_here(func): # <---- Point of interest print 'Yay, found a method ^_^ (unbound jet)' else: print 'Meh, just an ordinary function :/' return func class MyClass(object): @some_decorator def method(self): pass @some_decorator def function(): pass
4 Réponses :
Je compterais sur la Convention qui deviendrait que des méthodes deviendront un premier argument nommé Donc (pseudocode que j'ai des commentaires au lieu de ce que vous voulez faire dans les deux cas ...): P> auto code> et d'autres fonctions ne le font pas. Fragile, mais alors, il n'y a pas de manière vraiment solide.
class Foo(Bar): ... # no decorations
@decorator
def f(*a, **k): ...
Foo.f = f # "a killer"... function becomes method!
L'approche métaclasse l'a fait, merci! Je peux annuler les actions du décorateur pour des méthodes trouvées par métaclass .__ init __ code> sur la définition-time et réaménager le décorateur dans
basoclass .__ nouveau __ code> après l'initialisation, cette fois en utilisant l'instance limitée. méthode au lieu de la fonction non liée non liée à la méthode à une méthode.
Je pense que cela devrait être args = inspect.getargspec (f) .args code>
Juste pour le compte rendu des futurs lecteurs: le code est obsolète et l'approche est obsolète. (Évidemment, le poteau est assez vieux.) Utilisez l'approche par @kentwait.
Avez-vous besoin de faire passer la magie où vous choisissez quel emballage à retourner, ou pouvez-vous différer la magie jusqu'à ce que la fonction soit réellement appelée?
Vous pouvez toujours essayer un paramètre à votre décorateur pour indiquer lequel des deux emballages qu'il devrait utiliser, comme l'autre chose que je pourrais suggérer est de créer une métaclasse et de définir la
L'approche métaclasse l'a fait :) Votre solution fonctionne, mais je ne peux que «accepter» une seule réponse et Alex était le premier, désolé. Stackoverflow devrait permettre d'«accepter» plus d'une réponse ...
Il vous suffit de vérifier si la fonction étant décorée a un attribut note forte> que l'échantillon de code ci-dessous fait la détection au moment de l'appel, mais vous pouvez également le faire au moment de la décoration. Il suffit de déplacer le EDIT FORT> P> OH SNAP ! Et je l'obtiens totalement faux. Je so em> aurait dû lire la publication de Alex plus précisément. P> im_func code>. Si c'est le cas, c'est une méthode. Si ce n'est pas le cas, c'est une fonction.
HASATTR code> Cochez le générateur de décorateur externe. P>
de Python 3.3 en utilisant PEP 3155 :
def some_decorator(func): if func.__name__ != func.__qualname__: print('Yay, found a method ^_^ (unbound jet)') else: print('Meh, just an ordinary function :/') return func
L'approche moderne!