Стоит отметить, что для решения конкретной проблемы есть несколько альтернатив использования 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 предоставляет так много своих внутренних механизмов программисту, что вам редко нужно писать код, который пишет код.
exec/eval
и до сих пор не зналsetattr
?