Utilisation de l'introspection/réflexion

Fonctions

Contexte

Appeler des fonctions Python depuis une chaîne de caractères.

locals()['myfunc'](params)  # scope local voir help(locals)
globals()['myfunc'](params) # scope global voir help(globals)
eval('myfunc')(params)

Dans le cas des appels locals() et globals(), on récupère les symboles dans les dictionnaires respectifs locale et globale et on utilise pour clé le nom de la fonction pour accéder à notre fonction référencée dans le scope adéquat.

Utilisation

def hello(nick):
    print "Hello, your mail alias is %s@gcu.info" % nick
 
locals()['hello'](lutin)
globals()['hello'](lutin)
eval('hello')(lutin)
 
OUTPUT:
Hello, your mail alias is lutin@gcu.info
Hello, your mail alias is lutin@gcu.info
Hello, your mail alias is lutin@gcu.info

Autre utilisation : formatter les variables locales dans une chaine

bar = 42
baz = 'lorem ipsum'
quux = [1, 2, 3,]
print 'bar=%(bar)d, baz=%(baz)s, quux=%(quux)s' % locals()

OUTPUT:

bar=42, baz=lorem ipsum, quux=[1, 2, 3]

Méthodes d'instance

Contexte

Appeler des méthodes Python et Modifier des attributs depuis une chaîne de caractères.

getattr(instance,'myfunc')(params)
setattr(instance, attribute, value)
 
class GCU(object):
    def __init__(self, nick):
        self.nick = nick
    def get_nick(self):
        return self.nick
    def set_nick(self, new_nick):
        self.nick = new_nick
 
g = GCU('lutin')
g.get_nick()
g.set_nick('lutine')
getattr(g, 'get_nick')()
setattr(g, 'nick', 'lutin')
g.get_nick()
 
OUTPUT:
lutin
lutine
lutin

Jouer avec un object qu'on ne connait pas

Quand on utilise un objet ou une lib / whatever qu'on ne connait pas, perso je lis pas trop la doc parce que je suis un flemmeux et plutôt un curieux je fais :

print type(monobjet)
<class '__main__.MyClass'>

et la je me dis “ok faut voir plus loin”. La intervient “dir”. dir est un builtin qui retourne un peu tout ce qui forme l'objet qu'on lui balance en paramètre :

print dir(monobjet)
'__class__', '__delattr__', '__dict__', '__doc__', '__getattribute__', '__hash__', '__init__', '__module__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__str__', '__weakref__']

et la on a tout plein d'information sur l'objet et c'est un peu la fete.

regardez comme suit et je vous laisse deviner un peu :

chaine = "hello"
for attr in dir(chaine):
    if callable(attr):
        print "attr %s est une methode de : %s " % (attr, chaine.__class__.__name__)
    else:
        print "attr %s est un 'simple' attribut de %s" % (attr, chaine.__class__.__name__)

__dict__

Tous les objets possèdent un champ __dict__, un dict qui mappe les attributs (mais pas les méthodes, ou les champs par défauts) à leur valeur

class Foo(object):
    x = 1
    y = 2
    def __init__(self):
        self.x = 3
        self.z = 4
 
bar = Foo()
print bar.__dict__
bar.__dict__['a'] = 5
print bar.a

OUTPUT:

{'x': 3, 'z': 4}
5

Utilisation dans une chaine formattée

class Foo(object):
    def bar(self):
        self.baz = 42
        self.quux = [1, 2, 3,]
        print 'self.baz=%(baz)d, self.quux=%(quux)s' % self.__dict__
 
Foo().bar()

OUTPUT:

self.baz=42, self.quux=[1, 2, 3]
python/introspection.txt · Last modified: 2010/01/12 13:29 (external edit)
www.chimeric.de Creative Commons License Valid CSS Driven by DokuWiki do yourself a favour and use a real browser - get firefox!! Recent changes RSS feed Valid XHTML 1.0