IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Python Discussion :

Remonter au "caller"


Sujet :

Python

  1. #1
    Membre émérite
    Homme Profil pro
    Inscrit en
    Décembre 2007
    Messages
    758
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : France

    Informations professionnelles :
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Décembre 2007
    Messages : 758
    Par défaut Remonter au "caller"
    Bonjour,

    Je cherche un moyen pour pouvoir remonter au "caller" d'une fonction, mais je ne veux pas seulement son nom, je souhaite obtenir l'objet.

    Le module inspect me permet de remonter au nom du caller avec la méthode stack. Elle me permet aussi de remonter aux frames mais je ne sais pas comment les manipuler.

    Voici un exemple de ce que je voudrais faire:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    class Toto(object):
        get_caller() # => retourn l'objet class Toto
        def test(self):
            get_caller() # => retourne l'objet fonction test
    si quelqu'un a déjà essayé de faire ceci, je suis preneur de toute info

    D'avance merci

  2. #2
    Membre chevronné
    Avatar de vincent.mbg
    Homme Profil pro
    Développeur Python
    Inscrit en
    Décembre 2007
    Messages
    327
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Développeur Python

    Informations forums :
    Inscription : Décembre 2007
    Messages : 327
    Par défaut
    Bonsoir et bienvenue dans le monde de la Programmation Orienté Aspect

    Utilise les décorateurs

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
     
    def get_caller( foo ):
        print( foo )
        return foo
     
    class Toto( object ):
        @get_caller # => retourne l'objet class Toto
        def __init__( self ) :
            pass
     
        @get_caller # => retourne l'objet fonction test
        def test(self):
            pass
    Mon guide pour apprendre Tkinter - N'oubliez pas de consulter les FAQ Python ou de visiter mon blog

  3. #3
    Membre émérite
    Homme Profil pro
    Inscrit en
    Décembre 2007
    Messages
    758
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : France

    Informations professionnelles :
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Décembre 2007
    Messages : 758
    Par défaut
    Merci pour la réponse, je ne me suis jamais vraiment penché sur ces décorateurs (enfin à part les properties, classmethod et staticmethod), il va vraiment falloir que je m'y mette

    Je me rends compte que je n'ai pas été assez précis dans ma question.

    En fait, je n'ai besoin du caller qu'au moment de l'initialisation de la classe pour "customiser" la metaclass.

    Avec un décorateur sur le init, à chaque création d'instance je vais déclencher le mécanisme.

    J'ai cru comprendre que le mécanisme que je veux mettre en place s'appelle un "class advisor".

    Voici un exemple pour mieux comprendre:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    import inspect
    def test(name):
        caller = inspect.stack()[1][0]
        print caller.f_locals.keys()
        def advisor(name,bases,d):
            print "in advisor !"
            return type(name,bases,d)
        caller.f_locals["__defaultMetaclass__"] = caller.f_locals["__metaclass__"]
        caller.f_locals["__metaclass__"] = advisor
    class Meta(type):
        def __new__(cls,name,bases,d):
            print "in __new__"
            return type.__new__(cls,name,bases,d)
    class Item(object):
        __metaclass__ = Meta
        test("toto")
        def __init__(self):
            object.__init__(self)
    Dans l'exemple ci-dessus j'ai substitué la metaclass de Item par ma fonction advisor. Ce que je voudrais pouvoir faire, c'est faire en sorte qu'advisor fasse sa customisation de la classe et qu'il transmette ensuite la main à la métaclasse par défaut (celle que j'ai sauvegardé sous le nom "__defaultMetaclass__") et je ne sais pas comment l'invoquer.

    J'ai remarqué qu'en fait le caller de la métaclasse d'une classe est le module dans lequel est défini cette même classe.

    J'ai besoin de dissocier les mécanismes de customization de la class via la métaclasse et via le class advisor afin de pouvoir utiliser l'un sans l'autre.

    Je ne sais pas si c'est compréhensible, j'ai du mal à l'exprimer autrement.

  4. #4
    Membre émérite
    Homme Profil pro
    Inscrit en
    Décembre 2007
    Messages
    758
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : France

    Informations professionnelles :
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Décembre 2007
    Messages : 758
    Par défaut
    finalement, j'ai trouvé un package qui fait déjà ce que je souhaite: PyProtocols (c'est souvent bien mieux que de réinventer la roue :p)

    Voici la solution pour ceux que ça intéresse:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    from protocols.advice import addClassAdvisor
     
    def advice(name):
        def callback(cls):
            print "in callback"
            print cls
            setattr(cls,"__flagadvice__",True)
            return cls
        addClassAdvisor(callback)
     
    class Meta(type):
        def __new__(cls,name,bases,d):
            print "in __new__"
            d["__flagmeta__"] = True
            return type.__new__(cls,name,bases,d)
    class Base(object):
        __metaclass__ = Meta
        advice("base")
        def __init__(self):
            object.__init__(self)
    class Derived(Base):
        advice("derived")
        def __init__(self):
            Base.__init__(self)
     
    print Base.__dict__
    print Derived.__dict__
    Les classes ont bien été customisées à la fois par l'advisor et la metaclass et de manière indépendente l'une de l'autre. L'héritage ne pose pas de problème

+ Répondre à la discussion
Cette discussion est résolue.

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo