2015-10-09 14 views
5

Tiếp theo là phương pháp __init__ của lớp Local từ thư viện werkzeug:`đối tượng .__ setattr __ (self, ..., ...)` thay vì `setattr (self, ..., ...)`?

def __init__(self): 
    object.__setattr__(self, '__storage__', {}) 
    object.__setattr__(self, '__ident_func__', get_ident) 

Tôi không hiểu hai điều về mã này:

  1. Tại sao họ viết

    object.__setattr__(self, '__storage__', {}) 
    

    thay vì chỉ đơn giản là

    `setattr(self, '__storage__', {})` 
    
  2. Tại sao họ thậm chí sử dụng __setattr__ nếu chỉ đơn giản là có thể viết

    self.__storage__ = {} 
    

Trả lời

6

Điều này đảm bảo rằng định nghĩa Python mặc định là __setattr__ được sử dụng. Nó thường được sử dụng nếu lớp đã ghi đè __setattr__ để thực hiện hành vi không chuẩn, nhưng bạn vẫn muốn truy cập hành vi gốc __setattr__.

Trong trường hợp của Werkzeug, nếu bạn nhìn vào lớp Local bạn sẽ thấy __setattr__ được định nghĩa như thế này:

def __setattr__(self, name, value): 
    ident = self.__ident_func__() 
    storage = self.__storage__ 
    try: 
     storage[ident][name] = value 
    except KeyError: 
     storage[ident] = {name: value} 

Thay vì thiết lập các thuộc tính có trong từ điển của đối tượng, nó đặt chúng trong __storage__ từ điển đã được khởi tạo trước đó. Để đặt thuộc tính __storage__ ở tất cả (để nó có thể được truy cập như self.__storage__ sau), định nghĩa ban đầu của __setattr__ từ đối tượng phải được sử dụng, đó là lý do tại sao ký pháp khó xử được sử dụng trong hàm tạo.

+1

Tôi sẽ chỉ thêm rằng mặc dù có vẻ khó xử trong nguồn, nó cung cấp một giao diện đẹp cho người dùng của lớp. –

1

Bởi vì cùng lớp định nghĩa __setattr__ và điều này cần phải vượt qua đó, kể từ khi dòng đầu tiên nói self.__ident_func__() đó sẽ không làm việc.

2

Họ muốn sử dụng rõ ràng việc triển khai cơ sở object.__setattr__ thay vì phương pháp thể hiện phương pháp có thể bị ghi đè ở một nơi khác trong chuỗi kế thừa. Local thực hiện riêng __setattr__ để tránh điều này.

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