Hướng dẫn __slots__ python - __slots__ python
TLDR:Thuộc tính đặc biệt 0 cho phép bạn nêu rõ các thuộc tính mà bạn mong đợi các thể hiện đối tượng của mình sẽ có, với kết quả dự kiến: Show
Tiết kiệm không gian là từ
Nhanh chóng cảnh báoTriển lãm nhỏ, bạn chỉ nên khai báo một khe cụ thể một lần trong cây kế thừa. Ví dụ:
Python không phản đối khi bạn hiểu sai (có lẽ nó nên), các vấn đề có thể không biểu hiện, nhưng các đối tượng của bạn sẽ chiếm nhiều không gian hơn so với những gì họ nên làm. Python 3.8:
Điều này là do bộ mô tả khe của cơ sở có một khe tách biệt với sai. Điều này thường không nên xuất hiện, nhưng nó có thể:
Việc lưu ý lớn nhất là cho nhiều kế thừa - không thể kết hợp nhiều "lớp cha với các vị trí không trống". Để phù hợp với hạn chế này, hãy làm theo các thực tiễn tốt nhất: yếu tố tất cả trừ một hoặc tất cả sự trừu tượng của phụ huynh mà lớp cụ thể của họ tương ứng và lớp cụ thể mới của bạn sẽ được thừa hưởng từ - đưa ra các khe trống trừu tượng (giống như các lớp cơ sở trừu tượng trong Thư viện tiêu chuẩn). Xem phần về nhiều kế thừa dưới đây cho một ví dụ. Requirements:
Có rất nhiều chi tiết nếu bạn muốn tiếp tục đọc. Tại sao sử dụng >>> min(timeit.repeat(get_set_delete_fn(slotted))) 0.2846834529991611 >>> min(timeit.repeat(get_set_delete_fn(not_slotted))) 0.3664822799983085 0: Truy cập thuộc tính nhanh hơn.Người tạo ra Python, Guido Van Rossum, nói rằng ông thực sự đã tạo ra 0 để truy cập thuộc tính nhanh hơn.Thật tầm thường để chứng minh khả năng truy cập nhanh hơn có ý nghĩa đáng kể:
và
Truy cập có rãnh nhanh hơn gần 30% trong Python 3,5 trên Ubuntu.
Trong Python 2 trên Windows, tôi đã đo nó nhanh hơn khoảng 15%. Tại sao sử dụng >>> min(timeit.repeat(get_set_delete_fn(slotted))) 0.2846834529991611 >>> min(timeit.repeat(get_set_delete_fn(not_slotted))) 0.3664822799983085 0: Tiết kiệm bộ nhớMột mục đích khác của 0 là giảm không gian trong bộ nhớ mà mỗi trường hợp đối tượng chiếm.Đóng góp của riêng tôi cho tài liệu nêu rõ lý do đằng sau điều này:
SQLalchemy gán rất nhiều tiết kiệm bộ nhớ cho 0.Để xác minh điều này, sử dụng phân phối Anaconda của Python 2.7 trên Ubuntu Linux, với 9 (còn gọi là HEAPY) và 0, kích thước của một thể hiện lớp mà không có 0 được khai báo, và không có gì khác, là 64 byte. Điều đó không bao gồm 2. Cảm ơn bạn Python vì đã đánh giá lười biếng một lần nữa, 2 rõ ràng không được gọi là tồn tại cho đến khi nó được tham chiếu, nhưng các lớp không có dữ liệu thường là vô dụng. Khi được gọi vào sự tồn tại, thuộc tính 2 là tối thiểu là 280 byte.Ngược lại, một thể hiện lớp với 0 được tuyên bố là 6 (không có dữ liệu) chỉ là 16 byte và 56 byte tổng số với một mục trong các khe, 64 với hai.Đối với 64 bit Python, tôi minh họa mức tiêu thụ bộ nhớ trong các byte trong Python 2.7 và 3.6, cho 0 và 2 (không có vị trí nào được xác định) cho mỗi điểm mà dict
Vì vậy, mặc dù các dicts nhỏ hơn trong Python 3, chúng ta thấy tỷ lệ 0 độc đáo như thế nào để lưu bộ nhớ của chúng tôi và đó là một lý do chính mà bạn muốn sử dụng 0.Chỉ để hoàn thành các ghi chú của tôi, lưu ý rằng có chi phí một lần cho mỗi khe trong không gian tên của lớp là 64 byte trong Python 2 và 72 byte trong Python 3, vì các khe sử dụng mô tả dữ liệu như thuộc tính, được gọi là "thành viên".
Trình diễn >>> min(timeit.repeat(get_set_delete_fn(slotted))) 0.2846834529991611 >>> min(timeit.repeat(get_set_delete_fn(not_slotted))) 0.3664822799983085 0:Để từ chối việc tạo ra một 2, bạn phải phân lớp 8. Mọi thứ đều phân lớp 8 trong Python 3, nhưng trong Python 2, bạn phải rõ ràng:
now:
Hoặc lớp con khác xác định 0 0và bây giờ: 1but: 2Để cho phép tạo 2 trong khi phân lớp các đối tượng có rãnh, chỉ cần thêm 2 vào 0 (lưu ý rằng các khe được đặt hàng và bạn không nên lặp lại các vị trí đã có trong các lớp cha mẹ): 3và 4Truy cập có rãnh nhanh hơn gần 30% trong Python 3,5 trên Ubuntu. 5And: 6Tuy nhiên, 0 có thể gây ra vấn đề cho nhiều kế thừa: 7Bởi vì tạo ra một lớp con từ cha mẹ với cả hai khe không trống thất bại: 8Nếu bạn gặp phải vấn đề này, bạn có thể loại bỏ 0 khỏi cha mẹ hoặc nếu bạn có quyền kiểm soát cha mẹ, hãy cho họ các khe trống hoặc tái cấu trúc để trừu tượng hóa: 9Thêm >>> 0.3664822799983085 / 0.2846834529991611 1.2873325658284342 2 vào >>> min(timeit.repeat(get_set_delete_fn(slotted))) 0.2846834529991611 >>> min(timeit.repeat(get_set_delete_fn(not_slotted))) 0.3664822799983085 0 để nhận gán động: 0và bây giờ: 1Vì vậy, với 2 trong các khe cắm, chúng tôi mất một số lợi ích kích thước với mặt trái của việc gán động và vẫn có các khe cho những cái tên chúng tôi mong đợi.Khi bạn kế thừa từ một đối tượng không có rãnh, bạn sẽ nhận được cùng một loại ngữ nghĩa khi bạn sử dụng 0 - tên nằm trong 0 điểm đến các giá trị có rãnh, trong khi bất kỳ giá trị nào khác được đặt trong phiên bản 2.Tránh 0 vì bạn muốn có thể thêm các thuộc tính khi đang bay thực sự không phải là một lý do chính đáng - chỉ cần thêm 0 vào 0 của bạn nếu điều này là bắt buộc.Bạn có thể tương tự thêm 4 vào 0 rõ ràng nếu bạn cần tính năng đó.Được đặt thành Tuple trống khi phân lớp con có tênTuple:Bản dựng được đặt tên là các trường hợp bất biến rất nhẹ (về cơ bản là kích thước của các bộ dữ liệu) nhưng để có được lợi ích, bạn cần phải tự làm nếu bạn phân lớp chúng: 2usage: 3Và cố gắng gán một thuộc tính bất ngờ làm tăng 4 vì chúng tôi đã ngăn chặn việc tạo ra 2: 4Bạn có thể cho phép tạo 2 bằng cách bỏ 7, nhưng bạn không thể sử dụng 0 không trống với các loại phụ của tuple.Hãy cẩn thận nhất: Nhiều kế thừaNgay cả khi các khe không trống là giống nhau đối với nhiều cha mẹ, chúng không thể được sử dụng cùng nhau: 5Sử dụng 0 trống trong cha mẹ dường như cung cấp sự linh hoạt nhất, cho phép trẻ chọn ngăn chặn hoặc cho phép (bằng cách thêm 2 để nhận gán động, xem phần trên) Việc tạo ra 2:allowing the child to choose to prevent or allow (by adding 2 to get dynamic assignment, see section above) the creation of a 2: 6Bạn không cần phải có khe - vì vậy nếu bạn thêm chúng và loại bỏ chúng sau, nó không gây ra bất kỳ vấn đề nào. Đi ra ngoài ở đây: Nếu bạn sáng tác các bản phối hoặc sử dụng các lớp cơ sở trừu tượng, không có ý định được khởi tạo, một 0 in those parents seems to be the best way to go in terms of flexibility for subclassers.Để chứng minh, trước tiên, hãy tạo một lớp có mã mà chúng tôi muốn sử dụng trong nhiều kế thừa 7Chúng tôi có thể sử dụng trực tiếp các điều trên bằng cách kế thừa và khai báo các vị trí dự kiến: 8Nhưng chúng tôi không quan tâm đến điều đó, đó là sự thừa kế nhỏ, chúng tôi cần một lớp khác mà chúng tôi cũng có thể kế thừa, có thể với một thuộc tính ồn ào: 9Bây giờ nếu cả hai căn cứ đều có vị trí không trống, chúng tôi không thể làm dưới đây. . 0Và bây giờ chúng ta có chức năng từ cả thông qua nhiều kế thừa và vẫn có thể từ chối 2 và 4 Instantiation: 1Các trường hợp khác để tránh các khe:
Bạn có thể trêu chọc các cảnh báo thêm từ phần còn lại của tài liệu 0 (tài liệu 3.7 Dev là hiện tại nhất), mà tôi đã có những đóng góp đáng kể gần đây.Phê bình các câu trả lời khácCác câu trả lời hàng đầu hiện tại trích dẫn thông tin lỗi thời và khá léo tay và bỏ lỡ dấu ấn theo một số cách quan trọng. Không "chỉ sử dụng >>> min(timeit.repeat(get_set_delete_fn(slotted))) 0.2846834529991611 >>> min(timeit.repeat(get_set_delete_fn(not_slotted))) 0.3664822799983085 0 khi khởi tạo nhiều đối tượng"Tôi trích dẫn:
Các lớp cơ sở trừu tượng, ví dụ, từ mô -đun 10, không được khởi tạo, nhưng 0 được khai báo cho chúng.Why? Nếu người dùng muốn từ chối tạo 2 hoặc 4, những điều đó không có sẵn trong các lớp mẹ. 0 góp phần tái sử dụng khi tạo giao diện hoặc mixin.Đúng là nhiều người dùng Python không viết để tái sử dụng, nhưng khi bạn, có tùy chọn từ chối sử dụng không gian không cần thiết là có giá trị. >>> min(timeit.repeat(get_set_delete_fn(slotted))) 0.2846834529991611 >>> min(timeit.repeat(get_set_delete_fn(not_slotted))) 0.3664822799983085 0 không phá vỡ PicklingKhi ngâm một đối tượng có rãnh, bạn có thể thấy nó phàn nàn với một 16 gây hiểu lầm: 2Điều này thực sự không chính xác. Thông báo này xuất phát từ giao thức lâu đời nhất, là mặc định. Bạn có thể chọn giao thức mới nhất với đối số 17. Trong Python 2.7, điều này sẽ là 18 (được giới thiệu trong 2.3) và trong 3.6 là 19. 3Trong Python 2.7: 4trong Python 3.6 5Vì vậy, tôi sẽ ghi nhớ điều này, vì nó là một vấn đề được giải quyết. Phê bình về (cho đến ngày 2 tháng 10 năm 2016) đã chấp nhận câu trả lờiĐoạn đầu tiên là một nửa giải thích ngắn, một nửa dự đoán. Đây là phần duy nhất thực sự trả lời câu hỏi
Nửa thứ hai là suy nghĩ mong muốn, và tắt dấu:
Python thực sự làm một cái gì đó tương tự như thế này, chỉ tạo 2 khi nó được truy cập, nhưng việc tạo ra nhiều đối tượng không có dữ liệu là khá vô lý.Đoạn thứ hai quá mức và bỏ lỡ lý do thực tế để tránh 0. Dưới đây không phải là một lý do thực sự để tránh các vị trí (vì lý do thực tế, xem phần còn lại của câu trả lời của tôi ở trên.):
Sau đó, nó tiếp tục thảo luận về những cách khác để thực hiện mục tiêu đồi trụy đó với Python, không thảo luận bất cứ điều gì để làm với 0.Đoạn thứ ba là suy nghĩ mong muốn hơn. Cùng nhau, chủ yếu là nội dung ngoài thị trường mà người trả lời thậm chí không có tác giả và đóng góp cho đạn dược cho các nhà phê bình của trang web. Bằng chứng sử dụng bộ nhớTạo một số đối tượng bình thường và các đối tượng có rãnh: 6Khởi tạo một triệu trong số họ: 7Kiểm tra với 24: 8Truy cập các đối tượng thông thường và 2 của chúng và kiểm tra lại: 9Điều này phù hợp với lịch sử của Python, từ các loại và lớp thống nhất trong Python 2.2
|