Pergunta

Dada a função

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

existe uma maneira para mim para acessar seu get local () e as funções de pós () de uma maneira que eu posso chamá-los? Eu estou procurando uma função que irá funcionar como assim com a função f () definido acima:

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

Eu posso acessar os objetos de código para essas funções locais como assim

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

que resulta em

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

mas eu não consigo descobrir como obter os objetos de função que pode ser chamado reais. Isso é mesmo possível?

Obrigado por sua ajuda,

Will.

Foi útil?

Solução

Você está muito perto de fazer isso - módulo new apenas faltando:

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

Mas por que diabos se preocupar? Não é mais fácil a classe de uso? Instanciação parece com uma chamada de função de qualquer maneira.

Outras dicas

Você pode retornar funções como qualquer outro objeto em Python:

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


get, post = f()

Espero que isso ajude!

Note, porém, que, se você quiser usar o seu 'x' e 'y' variáveis ??get () ou post (), você deve fazer-lhes uma lista.

Se você fizer algo como isto:

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 irá referenciar uma lista diferente 'x' do que get2 e pós2.

Você pode usar exec para executar os objetos de código. Por exemplo, se você tivesse f definido como acima, então

exec(f.func_code.co_consts[3])

daria

get

como saída.

Os objetos de função internos não existem antes da função f () é executado. Se você quiser obtê-los você vai ter que construí-las sozinho. Isso é definitivamente não-trivial, pois eles podem ser fechamentos de que as variáveis ??de captura do âmbito da função e vai assim mesmo requerem que picam em torno de objetos que provavelmente deve ser considerado como detalhes de implementação do intérprete.

Se você quiser coletar as funções com menos repetição eu recomendo uma das seguintes abordagens:

a) Basta colocar as funções em uma definição de classe e retornar uma referência a essa classe. Uma coleção de funções relacionadas que são acessados ??pelo nome cheira terrivelmente como uma classe.

b) Criar uma subclasse dict que tem um método para registrar funções e usar isso como um decorador.

O código para esta seria algo parecido com isto:

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) fuçar em locals () e filtrar a função com inspect.isfunction. (Geralmente não uma boa idéia)

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top