Domanda

Scusa il titolo vago. Se qualcuno ha un suggerimento, per favore fatemi sapere! Ricalcola anche con tag più appropriati!

Il problema

Voglio che un'istanza di una classe importata sia in grado di visualizzare le cose nell'ambito (globali, locali) dell'importatore. Dato che non sono sicuro dell'esatto meccanismo al lavoro qui, posso descriverlo molto meglio con frammenti di parole.

## 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())

Quindi esegui questo codice da una sessione iterattiva, ci saranno molti 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()')

Esiste un linguaggio / modello comune per questo tipo di attività? Sto abbaiando completamente l'albero sbagliato?

È stato utile?

Soluzione

In questo esempio, puoi semplicemente consegnare le funzioni come oggetti ai metodi in C1 :

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

In Python, puoi passare funzioni e classi ad altri metodi e invocarli / crearli lì.

Se si desidera effettivamente valutare una stringa di codice, è necessario specificare l'ambiente, come già accennato da Thomas.

Il tuo modulo dall'alto, leggermente modificato:

## 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)

Ora, nell'interprete interattivo:

>>> 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!

Alcune annotazioni

  1. Qui inseriamo tutti gli oggetti da file1 nello spazio dei nomi di questo modulo
  2. f2 non si trova nello spazio dei nomi di file1 , quindi otteniamo un NameError
  3. Ora passiamo esplicitamente l'ambiente e il codice può essere valutato
  4. f1 si trova nello spazio dei nomi di questo modulo, perché lo abbiamo importato

Modifica : esempio di codice aggiunto su come passare esplicitamente l'ambiente per eval .

Altri suggerimenti

Le funzioni vengono sempre eseguite nell'ambito in cui sono definite, così come i metodi e i corpi di classe. Non vengono mai eseguiti in un altro ambito. Poiché l'importazione è solo un'altra istruzione di assegnazione e tutto in Python è un riferimento, le funzioni, le classi e i moduli non sanno nemmeno dove vengono importati.

Puoi fare due cose: passare esplicitamente l '"ambiente" che vuoi che usino, o usare lo stack hackery per accedere allo spazio dei nomi del loro chiamante. Il primo è di gran lunga preferito rispetto al secondo, in quanto non dipende dall'implementazione e fragile come il secondo.

Potresti voler guardare la classe string.Template, che prova a fare qualcosa di simile.

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