Какова область применения импортированных классов в Python?

StackOverflow https://stackoverflow.com/questions/117127

  •  02-07-2019
  •  | 
  •  

Вопрос

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

Проблема

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

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

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

Это было полезно?

Решение

В этом примере вы можете просто передать функции как объекты методам в 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.

Другие советы

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

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

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top