Domanda

Data la funzione

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

c'è un modo per accedere alle sue funzioni locali get () e post () in un modo che posso chiamarle? Sto cercando una funzione che funzioni così con la funzione f () definita sopra:

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

Posso accedere agli oggetti di codice per quelle funzioni locali in questo modo

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

che risulta in

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

ma non riesco a capire come ottenere gli oggetti funzione richiamabili. È anche possibile?

Grazie per l'aiuto,

Will.

È stato utile?

Soluzione

Sei abbastanza vicino a farlo - manca solo il modulo 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 :].

Ma perché diamine? Non è più facile usare la classe? L'istanza sembra comunque una chiamata di funzione.

Altri suggerimenti

Puoi restituire funzioni come qualsiasi altro oggetto in Python:

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


get, post = f()

Spero che questo aiuti!

Nota, tuttavia, che se vuoi usare le tue variabili 'x' e 'y' in get () o post (), dovresti renderle un elenco.

Se fai qualcosa del genere:

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 e post1 faranno riferimento a un elenco 'x' diverso rispetto a get2 e post2.

È possibile utilizzare exec per eseguire gli oggetti di codice. Ad esempio, se hai definito f come sopra, quindi

exec(f.func_code.co_consts[3])

darebbe

get

come output.

Gli oggetti funzione interni non esistono prima dell'esecuzione della funzione f (). Se vuoi ottenerli, dovrai costruirli tu stesso. Questo è sicuramente non banale perché potrebbero essere delle chiusure che catturano le variabili dall'ambito della funzione e richiedono comunque di frugare in oggetti che dovrebbero probabilmente essere considerati come dettagli di implementazione dell'interprete.

Se si desidera raccogliere le funzioni con meno ripetizioni, si consiglia uno dei seguenti approcci:

a) Basta inserire le funzioni in una definizione di classe e restituire un riferimento a quella classe. Una raccolta di funzioni correlate a cui si accede per nome ha un odore terribile come una classe.

b) Crea una sottoclasse dict che ha un metodo per registrare le funzioni e usala come decoratore.

Il codice per questo sarebbe simile a questo:

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) Cerca tra i locali () e filtra la funzione con inspect.isfunction. (di solito non è una buona idea)

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top