2010-06-29 36 views
12

tôi chỉ cần bỏ ra quá nhiều thời gian vào một lỗi như sau:Python: Lớp học có thể cấm khách hàng thiết lập thuộc tính mới không?

>>> class Odp(): 
    def __init__(self): 
     self.foo = "bar" 


>>> o = Odp() 
>>> o.raw_foo = 3 # oops - meant o.foo 

Tôi có một lớp học với một thuộc tính. Tôi đã cố gắng để thiết lập nó, và tự hỏi tại sao nó không có hiệu lực. Sau đó, tôi quay trở lại định nghĩa lớp gốc, và thấy rằng thuộc tính được đặt tên một cái gì đó hơi khác. Do đó, tôi đã tạo/thiết lập thuộc tính mới thay vì thuộc tính có nghĩa là.

Trước hết, đây không phải là chính xác loại lỗi mà ngôn ngữ gõ tĩnh được cho là sẽ ngăn không? Trong trường hợp này, lợi thế của gõ động là gì?

Thứ hai, có cách nào tôi có thể cấm điều này khi xác định Odp và do đó đã lưu bản thân sự cố không?

+1

Có thể trùng lặp: http://stackoverflow.com/questions/3079306/how-to-protect-againt-typos-when-setting-value-for-class-members – detly

Trả lời

16

Bạn có thể thực hiện một phương pháp __setattr__ cho mục đích này - đó là mạnh mẽ hơn nhiều so với __slots__ mà thường bị lạm dụng cho mục đích này (ví dụ, __slots__ là tự động "mất" khi lớp được thừa hưởng từ, trong khi __setattr__ sống sót trừ được ghi đè rõ ràng).

def __setattr__(self, name, value): 
    if hasattr(self, name): 
    object.__setattr__(self, name, value) 
    else: 
    raise TypeError('Cannot set name %r on object of type %s' % (
        name, self.__class__.__name__)) 

Bạn sẽ phải đảm bảo hasattr thành công cho tên bạn làm muốn để có thể thiết lập, ví dụ bằng cách thiết lập các thuộc tính ở mức lớp hoặc bằng cách sử dụng object.__setattr__ trong phương pháp __init__ của bạn chứ không phải hơn gán trực tiếp thuộc tính. (Để cấm đặt thuộc tính trên lớp thay vì trường hợp của bạn, bạn sẽ phải xác định metaclass tùy chỉnh bằng phương pháp đặc biệt tương tự).

+0

tại sao bạn chọn 'TypeError'? Có lẽ sai, tôi đã có 'AttributeError' trong tâm trí. Các thông báo – n611x007

+2

"không hỗ trợ gán XX" (ví dụ: đối với các mục) sử dụng 'TypeError', bị thêm nhiều từ" không có thuộc tính XX "sử dụng' AttributeError', vì vậy tôi đoán là OK (mặc dù không hoàn toàn). –

Các vấn đề liên quan