Perlu dicatat bahwa untuk masalah spesifik yang dimaksud, ada beberapa alternatif untuk menggunakan eval
:
Yang paling sederhana, seperti disebutkan, menggunakan setattr
:
def __init__(self):
for name in attsToStore:
setattr(self, name, None)
Pendekatan yang kurang jelas adalah memperbarui objek __dict__
objek secara langsung. Jika semua yang ingin Anda lakukan adalah menginisialisasi atribut None
, maka ini kurang mudah daripada di atas. Tetapi pertimbangkan ini:
def __init__(self, **kwargs):
for name in self.attsToStore:
self.__dict__[name] = kwargs.get(name, None)
Ini memungkinkan Anda meneruskan argumen kata kunci ke konstruktor, misalnya:
s = Song(name='History', artist='The Verve')
Ini juga memungkinkan Anda untuk membuat penggunaan Anda locals()
lebih eksplisit, misalnya:
s = Song(**locals())
... dan, jika Anda benar-benar ingin menetapkan None
atribut yang namanya ditemukan di locals()
:
s = Song(**dict([(k, None) for k in locals().keys()]))
Pendekatan lain untuk menyediakan objek dengan nilai default untuk daftar atribut adalah dengan mendefinisikan metode kelas __getattr__
:
def __getattr__(self, name):
if name in self.attsToStore:
return None
raise NameError, name
Metode ini dipanggil ketika atribut bernama tidak ditemukan dengan cara normal. Pendekatan ini agak kurang langsung daripada hanya mengatur atribut dalam konstruktor atau memperbarui __dict__
, tetapi memiliki manfaat tidak benar-benar membuat atribut kecuali jika ada, yang dapat secara substansial mengurangi penggunaan memori kelas.
Inti dari semua ini: Ada banyak alasan, secara umum, untuk dihindari eval
- masalah keamanan mengeksekusi kode yang tidak Anda kontrol, masalah praktis kode yang tidak dapat Anda debug, dll. Tapi alasan yang lebih penting adalah bahwa secara umum, Anda tidak perlu menggunakannya. Python memaparkan begitu banyak mekanisme internalnya kepada programmer sehingga Anda jarang benar-benar perlu menulis kode yang menulis kode.
exec/eval
dan masih belum tahusetattr
?