9
votes

Comment différencier la méthode et la fonction dans un décorateur?

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


0 commentaires

4 Réponses :


8
votes

Je compterais sur la Convention qui deviendrait que des méthodes deviendront un premier argument nommé auto code> et d'autres fonctions ne le font pas. Fragile, mais alors, il n'y a pas de manière vraiment solide.

Donc (pseudocode que j'ai des commentaires au lieu de ce que vous voulez faire dans les deux cas ...): P>

class Foo(Bar): ... # no decorations

@decorator
def f(*a, **k): ...

Foo.f = f   # "a killer"... function becomes method!


3 commentaires

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 __ sur la définition-time et réaménager le décorateur dans basoclass .__ nouveau __ 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


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.



1
votes

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 xxx

l'autre chose que je pourrais suggérer est de créer une métaclasse et de définir la init méthode dans la métaclasse pour rechercher des méthodes décorées avec votre décorateur et les réviser en conséquence, comme Alex allongé à. Utilisez cette métaclasse avec votre classe de base et, étant donné que toutes les classes qui utiliseront le décorateur hériteront de la classe de base, ils obtiendront également le type de métaclass et utilisent également son init aussi.


1 commentaires

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 ...



-3
votes

Il vous suffit de vérifier si la fonction étant décorée a un attribut im_func . Si c'est le cas, c'est une méthode. Si ce n'est pas le cas, c'est une fonction.

note 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 HASATTR Cochez le générateur de décorateur externe. xxx

EDIT

OH SNAP ! Et je l'obtiens totalement faux. Je so aurait dû lire la publication de Alex plus précisément. xxx


0 commentaires

7
votes

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


1 commentaires

L'approche moderne!