2014-12-05 2 views
1

Я хочу создать экземпляры класса из строки, которую пользователь ввел, поэтому я использовал функцию exec(). Проблема в том, что я не могу получить доступ к экземпляру по имени за пределами функции. Моя первая мысль заключалась в том, что это проблема с областью действия функции, и я все еще думаю, что это так, но когда я помещаю экземпляры в список, я могу получить к ним доступ, просто не используя их имя. Я не совсем уверен, что здесь происходит. Есть ли способ, чтобы я мог обращаться к экземплярам по их имени, например, thing1.properties, но вне функции, потому что это не весь мой код, поэтому было бы бесполезно помещать все вне функции ? Что-то вроде создания списка экземпляров в функции и «извлечения» всех экземпляров вне функции, чтобы я мог обращаться к ним за пределами функции. Вот код:Класс и область функций

class Things: 
    def __init__(self, properties): 
     self.properties = properties 

listt = [] 
def create_instance(): 
    exec("thing1=Things('good')") 
    listt.append(thing1) 

create_instance() 
print listt[0].properties 
print thing1.properties 
+4

Это почти наверняка очень плохой способ достижения своей цели , Что ты пытаешься сделать? – rlms

+0

Я написал в вопросе. Я хочу создать экземпляры класса из строки, которую пользователь набрал. Поэтому, когда пользователь вводит экземпляр объекта «thing1» thing1 = Things(). Если есть лучший способ сделать это, я бы сказал, что вы поделитесь им со мной. –

+3

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

ответ

1

В то время как я отрекаюсь загрязняют глобальное пространство имен, ехес оператор может принимать второй аргумент, который будет использоваться в качестве масштаба и значения по умолчанию, как locals():

>>> def foo(name): 
...  exec "{} = 1".format(name) 
... 
>>> def bar(name): 
...  exec "{} = 1".format(name) in globals() 
... 
>>> foo('a') 
>>> a 
Traceback (most recent call last): 
File "<stdin>", line 1, in <module> 
NameError: name 'a' is not defined 
>>> bar('a') 
>>> a 
1 

Так что, если вы передаете globals как область действия, она будет работать так, как вы хотите, но на самом деле? Загрязнение глобальной сферы само по себе является ужасным, делая это, в то время как оценка кода, предоставленного пользователем, является чертовой ответственностью.

[обновление]

Очень полезно! Спасибо! Но каков теперь лучший способ сделать это, словарь или глобальный масштаб?

Возможно, вы можете хранить все экземпляры в переменную класса, например:

class Thing(object): 
    instances = {} 
    def __init__(self, name, **properties): 
     self.name = name 
     self.properties = properties 
     self.instances[name] = self 
    def __repr__(self): 
     t = '<"{self.name}" thing, {self.properties}>' 
     return t.format(self=self) 

Теперь вы можете сделать:

# declare your things 
>>> Thing('foo', a=1, b=2) 
>>> Thing('bar', a=3, b=4) 

# retrieve them by name 
>>> Thing.instances.get('foo') 
<"foo" thing, {'a': 1, 'b': 2}> 

>>> Thing.instances.get('foo').properties 
{'a': 1, 'b': 2} 

>>> Thing.instances.get('bar').properties 
{'a': 3, 'b': 4} 
+0

Очень полезно! Спасибо! Но каков теперь лучший способ сделать это, словарь или глобальный масштаб? –

+0

@ NikolaLošić см. Мое обновление с предлагаемым подходом –

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