Варто зазначити, що для конкретної проблеми, про яку йдеться, існує кілька альтернатив використання 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
?