Pergunta

Por favor, desculpe o vago título. Se alguém tiver uma sugestão, por favor me avise! Além disso, reponha com tags mais apropriadas!

O problema

Quero ter uma instância de uma classe importada poder ver as coisas no escopo (globais, habitantes locais) do importador. Como não tenho certeza do mecanismo exato em ação aqui, posso descrevê -lo muito melhor com trechos do que palavras.

## File 1
def f1():  print "go f1!"

class C1(object):
    def do_eval(self,x):  # maybe this should be do_evil, given what happens
        print "evaling"
        eval(x)
        eval(x,globals(),locals())

Em seguida, execute este código de uma sessão iterativa, haverá muitos NameErrors

## interactive
class C2(object):
    def do_eval(self,x):  # maybe this should be do_evil, given what happens
        print "evaling"
        eval(x)
        eval(x,globals(),locals())

def f2():
    print "go f2!"

from file1 import C1
import file1

C1().do_eval('file1.f1()')
C1().do_eval('f1()')
C1().do_eval('f2()')

file1.C1().do_eval('file1.f1()')
file1.C1().do_eval('f1()')
file1.C1().do_eval('f2()')

C2().do_eval('f2()')
C2().do_eval('file1.f1()')
C2().do_eval('f1()')

Existe um idioma / padrão comum para esse tipo de tarefa? Estou latindo completamente a árvore errada?

Foi útil?

Solução

Neste exemplo, você pode simplesmente entregar funções como objetos aos métodos em C1:

>>> class C1(object):
>>>    def eval(self, x):
>>>        x()
>>>
>>> def f2(): print "go f2"
>>> c = C1()
>>> c.eval(f2)
go f2

No Python, você pode passar funções e classes para outros métodos e invocar/criá -los lá.

Se você deseja avaliar uma sequência de código, deve especificar o ambiente, como já mencionado por Thomas.

Seu módulo de cima, ligeiramente alterado:

## File 1
def f1():  print "go f1!"

class C1(object):
    def do_eval(self, x, e_globals = globals(), e_locals = locals()):
        eval(x, e_globals, e_locals)

Agora, no intérprete interativo:

>>> def f2():
>>>    print "go f2!"
>>> from file1 import *    # 1
>>> C1().do_eval("f2()")   # 2
NameError: name 'f2' is not defined

>>> C1().do_eval("f2()", globals(), locals()) #3
go f2!
>>> C1().do_eval("f1()", globals(), locals()) #4
go f1!

Algumas anotações

  1. Aqui, inserimos todos os objetos de file1 no espaço para nome deste módulo
  2. f2 não está no espaço de nome de file1, portanto, temos um NameError
  3. Agora passamos pelo ambiente explicitamente, e o código pode ser avaliado
  4. f1 está no espaço de nome deste módulo, porque nós o importamos

Editar: Amostra de código adicionada sobre como passar explicitamente o ambiente para eval.

Outras dicas

As funções são sempre executadas no escopo em que são definidas, assim como métodos e corpos de classe. Eles nunca são executados em outro escopo. Como a importação é apenas mais uma declaração de atribuição, e tudo no Python é uma referência, as funções, classes e módulos nem sabem para onde são importados.

Você pode fazer duas coisas: passar explicitamente o 'ambiente' que deseja que eles usem ou use o Stack Hackery para acessar o espaço para nome do chamador. O primeiro é muito preferido sobre o último, pois não depende da implementação e frágil como o último.

Você pode olhar para a classe String.Template, que tenta fazer algo semelhante.

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