Запрет на дыры безопасности, как eval
, нельзя использовать имя a
в mapper.py
, если только имя не определено где-то в mapper.py
или импортированы из другого модуля. Невозможно просто позволить mapper.py
автоматически и бесшумно получить доступ к значению a
из другого модуля.
Кроме того, если вы используете его только в дикторе, как в вашем примере, то a.foo
будет оцениваться сразу же после создания dict. Это не будет ждать, пока вы на самом деле вызовите функцию; как только он оценивает a.foo
, чтобы создать dict, он потерпит неудачу, потому что он не знает, что такое a
.
Вы можете обойти эту проблему, второй обернув элемент в функции (с помощью лямбда для краткости):
Mapper = {'test': lambda: a.foo}
. , , но это все равно не поможет, если вы не сможете каким-то образом получить a
, который будет доступен внутри mapper.py
.
Одним из возможных вариантов является параметризация ваш Mapper
от «загадочного» объекта, а затем передать этот объект из-за пределов:
# mapper.py
Mapper = {'test': lambda a: a.foo}
# other module
from mapper import Mapper
Mapper['test'](a)()
Или, подобное тому, что mgilson
предложил, вы можете «зарегистрировать» объект a
с Mapper
как-то. Это позволяет передать объект a
только один раз, чтобы зарегистрировать его, и тогда вы не должны передать его для каждого вызова:
# mapper.py
Mapper = {'test': lambda a: Mapper['a'].foo}
# other module
from mapper import Mapper
Mapper['a'] = a
Mapper['test']()()
Примечание два набора круглых скобках в конце концов там: один набор для оценки lambda и извлеките функцию, которую вы хотите вызвать, и второй набор, чтобы фактически вызвать эту функцию. Вы могли бы сделать подобное предложение, вместо того, чтобы использовать Mapper['a']
в качестве эталона, используя переменную уровня модуля:
# mapper.py
Mapper = {'test': lambda: a.foo}
# other module
import mapper
Mapper = mapper.Mapper
mapper.a = a
Mapper['test']()()
Обратите внимание, что это требует от вас сделать import mapper
для того, чтобы установить переменную модуля в этом другом модуле.
Вы можете упростить эту процедуру, используя собственный класс для Mapper
вместо обычного dict, и чтобы этот класс работал в своем __getitem__
, чтобы посмотреть в «известном месте» (например, прочитать некоторую переменную модуля), чтобы использовать в качестве основы для оценки a
. Тем не менее, это будет более тяжелое решение.
Суть заключается в том, что вы просто не можете (опять же, без использования eval
или других подобных отверстий) писать код в mapper.py
, который использует неопределенную переменная a
, а затем определить в другом модуле переменной a
и иметь mapper.py
автоматически знать об этом. Там должна быть какая-то строка кода, где «говорит» mapper.py
какое значение a
вы хотите использовать.
Нет сожаления, что это не то, что я хочу. Полное определение функции должно быть указано в 'mapper.py' для любого экземпляра' a'. Неизвестно заранее, что такое 'a'. Я буду опрокидываться в вопросе. – Alex
@Alex: Вы не можете ожидать «полного определения», если вы не знаете, что такое объект. В какой-то момент вам нужно будет указать, что это за объект. – BrenBarn