Pregunta

Dada la función

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

¿hay alguna forma de acceder a sus funciones locales get () y post () de forma que pueda llamarlas? Estoy buscando una función que funcione así con la función f () definida anteriormente:

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

Puedo acceder a los objetos de código para esas funciones locales así

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

que da como resultado

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

pero no puedo entender cómo obtener los objetos de función invocables reales. ¿Es eso posible?

Gracias por su ayuda,

Will.

¿Fue útil?

Solución

Estás bastante cerca de hacerlo, solo falta el módulo new :

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

¿Pero por qué se molestan? ¿No es más fácil usar la clase? La creación de instancias parece una llamada de función de todos modos.

Otros consejos

Puede devolver funciones como cualquier otro objeto en Python:

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


get, post = f()

¡Espero que esto ayude!

Tenga en cuenta, sin embargo, que si desea utilizar sus variables 'x' e 'y' en get () o post (), debe hacerlas una lista.

Si haces algo como esto:

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 y post1 harán referencia a una lista 'x' diferente de get2 y post2.

Podría usar exec para ejecutar los objetos de código. Por ejemplo, si tenía f definida como anteriormente, entonces

exec(f.func_code.co_consts[3])

daría

get

como salida.

Los objetos de la función interna no existen antes de que se ejecute la función f (). Si desea obtenerlos, deberá construirlos usted mismo. Eso definitivamente no es trivial porque podrían ser cierres que capturan variables del alcance de la función y de todos modos requerirán hurgar en objetos que probablemente deberían considerarse como detalles de implementación del intérprete.

Si desea recopilar las funciones con menos repetición, le recomiendo uno de los siguientes enfoques:

a) Simplemente ponga las funciones en una definición de clase y devuelva una referencia a esa clase. Una colección de funciones relacionadas a las que se accede por nombre huele terriblemente a una clase.

b) Cree una subclase dict que tenga un método para registrar funciones y úsela como decorador.

El código para esto se vería así:

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) Examine los locales () y filtre la función con inspect.isfunction. (generalmente no es una buena idea)

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top