2012-11-09 3 views
2

Контекст: Я делаю игру Ren'py. Значение Character(). Да, я знаю, что это глупая идея вне этого контекста.Создание глобальной переменной (из строки) из класса

Мне нужно создать переменную из входной строки внутри класса, который существует за пределами класса сферы:

class Test: 
    def __init__(self): 
     self.dict = {} # used elsewhere to give the inputs for the function below. 

    def create_global_var(self, variable, value): 
     # the equivalent of exec("global {0}; {0} = {1}".format(str(variable), str(value))) 
     # other functions in the class that require this. 

Test().create_global_var("abc", "123") # hence abc = 123 

Я попытался vars()[], globals()[variable] = value, и т.д., и они просто не работают (они даже не определяют ничего) Редактировать: это была моя проблема.

Я знаю, что следующий будет работать одинаково хорошо, но я хочу, переменные в правильном объеме:

setattr(self.__class__, variable, value) # d.abc = 123, now. but incorrect scope. 

Как создать переменную в глобальной области видимости внутри класса, используя строку как имя переменной, без использования атрибутов или exec в python?

И да, я буду проверять работоспособность.

+0

Если вы говорите, что это «глупая идея», почему бы не подумать о лучшей? – iTayb

+0

Я говорю это просто из-за похожих вопросов, которые я видел, спросил, что результат в 20 ответов, которые не отвечают на исходный вопрос, и просто скажите, какая плохая идея – Amelia

+0

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

ответ

4

Прежде всего: то, что мы называем «глобальной» областью в Python, на самом деле является «модульной» областью (с другой стороны, оно уменьшает «зло» использования глобальных варов).

Тогда для создания глобальной переменной динамически, хотя я до сих пор не могу понять, почему это было бы быть лучше, чем с использованием словаря уровня модуля, просто сделать:

globals()[variable] = value 

Это создает переменную в текущем модуль. Если вам необходимо создать переменный модуль на модуле, из которого был вызван метод, вы можете заглянуть в словарь глобал из кадра вызывающего абонента с помощью:

from inspect import currentframe 
currentframe(1).f_globals[variable] = name 

Теперь это, кажется, специально бесполезно, так как вы можете создать переменную с динамическим именем, но вы не можете получить доступ к нему динамически (если снова не использовать словарь глобалов)

Даже в вашем тестовом примере вы создаете переменную «abc», передавая метод строке, но тогда вам нужно получить доступ это с помощью жестко закодированного «abc» - сам язык предназначен для предотвращения этого (отсюда и разница в Javascript, где индексы массива и атрибуты объекта являются взаимозаменяемыми, тогда как в Python у вас есть distinc Mapping объекты)

Мое предложение состоит в том, что вы используете явный словарь уровня модуля и создать все динамические переменные в виде пар ключ/значение там:

names = {} 
class Test(object): 
    def __init__(self): 
     self.dict = {} # used elsewhere to give the inputs for the function below. 

    def create_global_var(self, variable, value): 
     names[variable] = value 

(на стороне записки, в Pyhton 2 всегда унаследовать классы из «объекта»)

+0

OP утверждал, что это не работает для них. Но он должен: >>> класс A (объект): ... def foo (self, bar): ... globals() ['foo'] = bar ... >>> A () .foo ('asdf') >>> foo 'asdf' – Iguananaut

+0

странно, когда я впервые попробовал это, он не сработал. Я снова попытался, и он действительно работает. то опять же, я использую собственный интерпретатор, запущенный внутри игрового движка, следовательно, странная потребность в этом. – Amelia

+1

@Iguananaut: Возможно, это не сработает из-за ['__main__' gotcha] (http://ideone.com/0L0c5i). Модуль может быть доступен с помощью разных имен. 'globals()' относится к модулю, функция определена в i.e, 'globals()' inside 'mod.func()' относится к переменным mod. – jfs

2

Для этого можно использовать setattr(__builtins__, 'abc', '123').

Имейте в виду, что это скорее всего проблема дизайна, и вы должны пересмотреть дизайн.

+1

Вы не должны касаться '__builtins__', это детализация реализации CPython. –

Смежные вопросы