Стоит отметить, что для конкретной проблемы существует несколько альтернатив использованию eval
:
Самое простое, как уже отмечалось, использует setattr
:
def __init__(self):
for name in attsToStore:
setattr(self, name, None)
Менее очевидный подход - непосредственное обновление объекта __dict__
. Если все, что вы хотите сделать, это инициализировать атрибуты None
, то это не так просто, как указано выше. Но учтите это:
def __init__(self, **kwargs):
for name in self.attsToStore:
self.__dict__[name] = kwargs.get(name, None)
Это позволяет передавать аргументы ключевого слова в конструктор, например ::
s = Song(name='History', artist='The Verve')
Это также позволяет вам сделать использование locals()
более явным, например ::
s = Song(**locals())
... и, если вы действительно хотите присвоить None
атрибутам, имена которых находятся в locals()
:
s = Song(**dict([(k, None) for k in locals().keys()]))
Другой подход к предоставлению объекту значений по умолчанию для списка атрибутов состоит в определении метода __getattr__
класса:
def __getattr__(self, name):
if name in self.attsToStore:
return None
raise NameError, name
Этот метод вызывается, когда именованный атрибут не найден обычным способом. Этот подход несколько менее прост, чем просто установка атрибутов в конструкторе или обновление __dict__
, но он имеет преимущество в том, что фактически не создает атрибут, если он не существует, что может существенно уменьшить использование памяти классом.
Суть всего этого: в общем, существует множество причин, по которым следует избегать eval
- проблема безопасности выполнения кода, который вы не контролируете, практическая проблема кода, который вы не можете отлаживать, и т. Д. Но еще более важной причиной является то, что вам вообще не нужно его использовать. Python предоставляет так много своих внутренних механизмов программисту, что вам действительно не нужно писать код, который пишет код.