Question

Étant donné la fonction

def f():
    x, y = 1, 2 
    def get():
        print 'get'
    def post():
        print 'post'

puis-je accéder aux fonctions locales get () et post () de manière à ce que je puisse les appeler? Je cherche une fonction qui fonctionnera comme avec la fonction f () définie ci-dessus:

>>> get, post = get_local_functions(f)
>>> get()
'get'

Je peux accéder aux objets de code pour les fonctions locales telles que

import inspect
for c in f.func_code.co_consts:
    if inspect.iscode(c):
        print c.co_name, c

ce qui entraîne

get <code object get at 0x26e78 ...>
post <code object post at 0x269f8 ...>

mais je ne vois pas comment obtenir les objets de fonction appelables. Est-ce même possible?

Merci de votre aide,

Will.

Était-ce utile?

La solution

Vous êtes sur le point de le faire - il manque juste le nouveau module:

import inspect
import new

def f():
    x, y = 1, 2
    def get():
        print 'get'
    def post():
        print 'post'

for c in f.func_code.co_consts:
    if inspect.iscode(c):
        f = new.function(c, globals())
        print f # Here you have your function :].

Mais pourquoi diable dérange-t-il? N'est-ce pas plus facile d'utiliser la classe? L’instanciation ressemble quand même à un appel de fonction.

Autres conseils

Vous pouvez renvoyer des fonctions comme n'importe quel autre objet Python:

def f():
    x, y = 1, 2 
    def get():
        print 'get'
    def post():
        print 'post'
    return (get, post)


get, post = f()

J'espère que ça aide!

Notez cependant que si vous souhaitez utiliser vos variables 'x' et 'y' dans get () ou post (), vous devez en faire une liste.

Si vous faites quelque chose comme ça:

def f():
    x = [1]
    def get():
        print 'get', x[0]
        x[0] -= 1
    def post():
        print 'post', x[0]
        x[0] += 1
    return (get, post)

get1, post1 = f()
get2, post2 = f()

get1 et post1 référenceront une liste 'x' différente de celle de get2 et post2.

Vous pouvez utiliser exec pour exécuter les objets de code. Par exemple, si vous avez défini f comme ci-dessus, alors

exec(f.func_code.co_consts[3])

donnerait

get

en sortie.

Les objets fonction internes n'existent pas avant l'exécution de la fonction f (). Si vous voulez les obtenir, vous devrez les construire vous-même. C’est certainement non trivial, car il peut s’agir de fermetures capturant des variables du champ de la fonction et nécessitant de toute façon des fouilles dans des objets qui devraient probablement être considérés comme des détails d’implémentation de l’interprète.

Si vous souhaitez collecter les fonctions avec moins de répétition, nous vous recommandons l'une des approches suivantes:

a) Il suffit de placer les fonctions dans une définition de classe et de renvoyer une référence à cette classe. Un ensemble de fonctions connexes auxquelles on accède par nom sent terriblement comme une classe.

b) Créez une sous-classe dict qui possède une méthode d’enregistrement des fonctions et utilisez-la comme décoratrice.

Le code correspondant à ceci ressemblerait à ceci:

class FunctionCollector(dict):
    def register(self, func):
        self[func.__name__] = func

def f():
    funcs = FunctionCollector()
    @funcs.register
    def get():
        return 'get'
    @funcs.register
    def put():
        return 'put'
    return funcs

c) Rechercher dans les sections locales () et filtrer la fonction avec inspect.isfunction. (généralement pas une bonne idée)

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top