Điều đáng chú ý là đối với vấn đề cụ thể đang được đề cập, có một số lựa chọn thay thế cho việc sử dụng eval
:
Đơn giản nhất, như đã lưu ý, là sử dụng setattr
:
def __init__(self):
for name in attsToStore:
setattr(self, name, None)
Một cách tiếp cận ít rõ ràng hơn là cập nhật __dict__
trực tiếp đối tượng của đối tượng. Nếu tất cả những gì bạn muốn làm là khởi tạo các thuộc tính None
, thì điều này ít đơn giản hơn so với ở trên. Nhưng hãy xem xét điều này:
def __init__(self, **kwargs):
for name in self.attsToStore:
self.__dict__[name] = kwargs.get(name, None)
Điều này cho phép bạn chuyển các đối số từ khóa cho hàm tạo, ví dụ:
s = Song(name='History', artist='The Verve')
Nó cũng cho phép bạn sử dụng locals()
rõ ràng hơn, ví dụ:
s = Song(**locals())
... và, nếu bạn thực sự muốn gán None
cho các thuộc tính có tên được tìm thấy trong locals()
:
s = Song(**dict([(k, None) for k in locals().keys()]))
Một cách tiếp cận khác để cung cấp một đối tượng với các giá trị mặc định cho danh sách các thuộc tính là xác định __getattr__
phương thức của lớp :
def __getattr__(self, name):
if name in self.attsToStore:
return None
raise NameError, name
Phương thức này được gọi khi thuộc tính được đặt tên không được tìm thấy theo cách thông thường. Cách tiếp cận này hơi đơn giản hơn là chỉ đơn giản là đặt các thuộc tính trong hàm tạo hoặc cập nhật__dict__
, nhưng nó có ưu điểm là không thực sự tạo thuộc tính trừ khi nó tồn tại, điều này có thể làm giảm đáng kể việc sử dụng bộ nhớ của lớp.
Vấn đề của tất cả những điều này: nói chung, có rất nhiều lý do để tránh eval
- vấn đề bảo mật khi thực thi mã mà bạn không kiểm soát, vấn đề thực tế về mã bạn không thể gỡ lỗi, v.v. Nhưng một lý do thậm chí còn quan trọng hơn nói chung là bạn không cần sử dụng nó. Python tiết lộ rất nhiều cơ chế bên trong của nó cho lập trình viên mà bạn hiếm khi thực sự cần phải viết mã viết mã.
exec/eval
và vẫn không biếtsetattr
?