Какова область применения импортируемых классов в Python? - PullRequest
2 голосов
/ 22 сентября 2008

Пожалуйста, извините за смутное название. Если у кого-нибудь есть предложение, пожалуйста, дайте мне знать! Также, пожалуйста, пометьте теги с более подходящими тегами!

Проблема

Я хочу, чтобы экземпляр импортируемого класса мог просматривать вещи в области видимости (глобальные, локальные) импортера. Поскольку я не уверен в точном механизме работы здесь, я могу описать его гораздо лучше с помощью фрагментов, чем слов.

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

Затем запустите этот код из итеративного сеанса, там будет много 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()')

Существует ли распространенная идиома / шаблон для такого рода задач? Я полностью лаю не на том дереве?

Ответы [ 2 ]

1 голос
/ 23 сентября 2008

В этом примере вы можете просто передать функции как объекты методам в C1:

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

В Python вы можете передавать функции и классы другим методам и вызывать / создавать их там.

Если вы действительно хотите оценить строку кода, вы должны указать среду, как уже упоминалось Томасом.

Ваш модуль сверху немного изменен:

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

Теперь в интерактивном переводчике:

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

Некоторые аннотации

  1. Здесь мы вставляем все объекты из file1 в пространство имен этого модуля
  2. f2 не находится в пространстве имен file1, поэтому мы получаем NameError
  3. Теперь мы явно передаем среду, и код может быть оценен
  4. f1 находится в пространстве имен этого модуля, потому что мы импортировали его

Редактировать : Добавлен пример кода о том, как явно передать среду для eval.

1 голос
/ 22 сентября 2008

Функции всегда выполняются в той области, в которой они определены, как и методы и тела классов. Они никогда не выполняются в другом объеме. Поскольку импорт - это просто еще один оператор присваивания, а все в Python является ссылкой, функции, классы и модули даже не знают, куда они импортируются.

Вы можете сделать две вещи: явно передать «среду», которую вы хотите, чтобы они использовали, или использовать хакерство стека для доступа к пространству имен своего вызывающего. Первое значительно предпочтительнее второго, так как оно не так зависит от реализации и хрупко, как второе.

Возможно, вы захотите взглянуть на класс string.Template, который пытается сделать нечто подобное.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...