Đối tượng python nhỏ hơn
Có thể lấy phiên bản PDF của hướng dẫn này từ trang web của tôi hoặc Github. Hướng dẫn phương pháp ma thuật có kho lưu trữ git tại http. //www. github. com/RafeKettler/magicmethods. Mọi vấn đề có thể được báo cáo ở đó, cùng với nhận xét, (hoặc thậm chí là đóng góp. ) Mục lục Hướng dẫn này là đỉnh cao của các bài đăng trên blog trong vài tháng. Chủ đề là phương pháp ma thuật Phương pháp ma thuật là gì? . Chúng là các phương thức đặc biệt mà bạn có thể định nghĩa để thêm "ma thuật" vào các lớp của mình. Chúng luôn được bao quanh bởi hai dấu gạch dưới (e. g. 8 hoặc 9). Chúng cũng không được ghi lại đầy đủ như chúng cần. Tất cả các phương pháp kỳ diệu cho Python xuất hiện trong cùng một phần trong tài liệu Python, nhưng chúng nằm rải rác và chỉ được tổ chức lỏng lẻo. Hầu như không có ví dụ nào được tìm thấy trong phần đó (và điều đó rất có thể là do thiết kế, vì tất cả chúng đều được trình bày chi tiết trong tài liệu tham khảo ngôn ngữ, cùng với các mô tả cú pháp nhàm chán, v.v. )Vì vậy, để khắc phục những gì tôi coi là lỗ hổng trong tài liệu của Python, tôi đã bắt đầu cung cấp một số tài liệu dựa trên ví dụ, bằng tiếng Anh đơn giản hơn cho các phương thức ma thuật của Python. Tôi bắt đầu với các bài đăng trên blog hàng tuần và bây giờ tôi đã hoàn thành các bài đăng đó, tôi đã tổng hợp hướng dẫn này tôi hy vọng bạn thích nó. Sử dụng nó như một hướng dẫn, bồi dưỡng hoặc tham khảo; Mọi người đều biết phương pháp ma thuật cơ bản nhất, 8. Đó là cách mà chúng ta có thể xác định hành vi khởi tạo của một đối tượng. Tuy nhiên, khi tôi gọi cho 1, 8 không phải là người đầu tiên được gọi. Trên thực tế, đó là một phương thức có tên là 3, thực sự tạo ra thể hiện, sau đó chuyển bất kỳ đối số nào khi tạo vào trình khởi tạo. Ở đầu kia của tuổi thọ của đối tượng, có 4. Hãy cùng tìm hiểu kỹ hơn về 3 phương pháp kỳ diệu này 5 3 là phương thức đầu tiên được gọi trong phần khởi tạo của đối tượng. Nó lấy lớp, sau đó bất kỳ đối số nào khác mà nó sẽ chuyển đến 8. 3 được sử dụng khá hiếm, nhưng nó có mục đích của nó, đặc biệt khi phân lớp con một loại bất biến như một bộ hoặc một chuỗi. Tôi không muốn đi vào quá nhiều chi tiết về 3 vì nó không quá hữu ích, nhưng nó được trình bày rất chi tiết trong tài liệu Python. 20Trình khởi tạo cho lớp. Nó được truyền bất cứ thứ gì hàm tạo chính được gọi với (vì vậy, ví dụ: nếu chúng ta gọi là 21, thì 8 sẽ được truyền là 23 và 24 làm đối số. 8 hầu như được sử dụng phổ biến trong các định nghĩa lớp Python. 26Nếu 3 và 8 tạo thành hàm tạo của đối tượng, thì 4 là hàm hủy. Nó không triển khai hành vi cho câu lệnh 20 (do đó mã sẽ không dịch thành 21). Thay vào đó, nó xác định hành vi khi một đối tượng được thu gom rác. Nó có thể khá hữu ích cho các đối tượng có thể yêu cầu dọn dẹp thêm khi xóa, như ổ cắm hoặc đối tượng tệp. Tuy nhiên, hãy cẩn thận vì không có gì đảm bảo rằng 4 sẽ được thực thi nếu đối tượng vẫn còn hoạt động khi trình thông dịch thoát ra, do đó, 4 không thể đóng vai trò thay thế cho các phương pháp mã hóa tốt (chẳng hạn như luôn đóng kết nối khi bạn thực hiện xong . Trên thực tế, 4 hầu như không bao giờ được sử dụng vì hoàn cảnh bấp bênh mà nó được gọi; Đặt tất cả lại với nhau, đây là một ví dụ về hoạt động của 8 và 4 9Một trong những lợi thế lớn nhất của việc sử dụng các phương thức kỳ diệu của Python là chúng cung cấp một cách đơn giản để làm cho các đối tượng hoạt động giống như các kiểu dựng sẵn. Điều đó có nghĩa là bạn có thể tránh được những cách thực hiện toán tử cơ bản xấu xí, phản trực giác và không chuẩn. Trong một số ngôn ngữ, việc làm như thế này là phổ biến
Bạn chắc chắn cũng có thể làm điều này trong Python, nhưng điều này làm tăng thêm sự nhầm lẫn và dài dòng không cần thiết. Các thư viện khác nhau có thể sử dụng các tên khác nhau cho cùng một hoạt động, khiến máy khách thực hiện nhiều công việc hơn mức cần thiết. Tuy nhiên, với sức mạnh của các phương thức ma thuật, chúng ta có thể định nghĩa một phương thức (trong trường hợp này là ____227) và thay vào đó hãy nói ý của chúng ta
Đó là một phần sức mạnh của phương pháp ma thuật. Phần lớn trong số chúng cho phép chúng ta định nghĩa ý nghĩa cho các toán tử để chúng ta có thể sử dụng chúng trên các lớp của riêng mình giống như chúng được xây dựng trong các kiểu Python có một loạt các phương thức ma thuật được thiết kế để thực hiện so sánh trực quan giữa các đối tượng bằng cách sử dụng toán tử, không gọi phương thức khó xử. Họ cũng cung cấp một cách để ghi đè hành vi Python mặc định để so sánh các đối tượng (bằng cách tham khảo). Đây là danh sách các phương pháp đó và những gì họ làm 28 29 là phương pháp ma thuật so sánh cơ bản nhất. Nó thực sự thực hiện hành vi cho tất cả các toán tử so sánh (<, ==,. =, v.v. ), nhưng nó có thể không hoạt động theo cách bạn muốn (ví dụ: liệu một trường hợp có bằng một trường hợp khác được xác định bởi một tiêu chí hay không và liệu một trường hợp có lớn hơn một trường hợp khác hay không được xác định bởi một yếu tố khác). 29 sẽ trả về một số nguyên âm nếu 61, 0 nếu 62 và dương nếu 63. Thông thường, tốt nhất là xác định từng phép so sánh mà bạn cần thay vì xác định tất cả chúng cùng một lúc, nhưng 29 có thể là một cách hay để tiết kiệm sự lặp lại và cải thiện sự rõ ràng khi bạn cần thực hiện tất cả phép so sánh với các tiêu chí tương tự. 65Xác định hành vi cho toán tử bình đẳng, 66. 67Xác định hành vi cho toán tử bất đẳng thức, 68. 69Xác định hành vi cho toán tử nhỏ hơn, 50. 51Xác định hành vi cho toán tử lớn hơn, 52. 53Xác định hành vi cho toán tử nhỏ hơn hoặc bằng, 54. ________ 455 Xác định hành vi cho toán tử lớn hơn hoặc bằng, ________ 456Ví dụ, hãy xem xét một lớp để mô hình hóa một từ. Chúng tôi có thể muốn so sánh các từ theo từ điển (theo bảng chữ cái), đây là hành vi so sánh mặc định cho các chuỗi, nhưng chúng tôi cũng có thể muốn làm điều đó dựa trên một số tiêu chí khác, chẳng hạn như độ dài hoặc số lượng âm tiết. Trong ví dụ này, chúng ta sẽ so sánh theo độ dài. Đây là một triển khai 2Bây giờ, chúng ta có thể tạo hai 57 (bằng cách sử dụng 58 và 59) và so sánh chúng dựa trên độ dài. Tuy nhiên, lưu ý rằng chúng tôi không định nghĩa 27 và 71. Điều này là do điều này sẽ dẫn đến một số hành vi kỳ lạ (đáng chú ý là 72 sẽ đánh giá là đúng). Sẽ không có ý nghĩa gì khi kiểm tra sự bình đẳng dựa trên độ dài, vì vậy chúng tôi quay trở lại việc triển khai bình đẳng của 73Bây giờ sẽ là thời điểm tốt để lưu ý rằng bạn không cần phải xác định mọi phương pháp ma thuật so sánh để có được các phép so sánh phong phú. Thư viện tiêu chuẩn đã vui lòng cung cấp cho chúng tôi một trình trang trí lớp trong mô-đun 74 sẽ xác định tất cả các phương thức so sánh phong phú nếu bạn chỉ định nghĩa 27 và một phương thức khác (e. g. 76, 9, v.v. ) Tính năng này chỉ khả dụng trong Python 2. 7, nhưng khi bạn có cơ hội, nó sẽ tiết kiệm rất nhiều thời gian và công sức. Bạn có thể sử dụng nó bằng cách đặt 78 phía trên định nghĩa lớp của bạnGiống như bạn có thể tạo các cách để các thể hiện của lớp được so sánh với các toán tử so sánh, bạn có thể xác định hành vi cho các toán tử số. Thắt dây an toàn đi mọi người. có rất nhiều trong số này. Vì lợi ích của tổ chức, tôi đã chia các phương pháp ma thuật số thành 5 loại. toán tử một ngôi, toán tử số học bình thường, toán tử số học được phản ánh (sẽ nói thêm về điều này sau), phép gán tăng cường và chuyển đổi kiểu Các toán tử và hàm một ngôiCác toán tử và hàm một ngôi chỉ có một toán hạng, e. g. phủ định, giá trị tuyệt đối, v.v. 79Thực hiện hành vi cho tích cực đơn phương (e. g. 60) 61Thực hiện hành vi phủ định (e. g. 62) 63Thực hiện hành vi cho chức năng 64 tích hợp. 65Thực hiện hành vi để đảo ngược bằng cách sử dụng toán tử 66. Để được giải thích về những gì điều này làm, hãy xem bài viết trên Wikipedia về hoạt động bitwise. 67Triển khai hành vi cho hàm 68 tích hợp. 69 là số chữ số thập phân cần làm tròn đến. 60Thực hiện hành vi cho 61, i. e. , làm tròn xuống số nguyên gần nhất. 62Thực hiện hành vi cho 63, tôi. e. , làm tròn lên đến số nguyên gần nhất. 64Thực hiện hành vi cho 65, i. e. , rút gọn thành tích phânToán tử số học bình thườngBây giờ, chúng tôi đề cập đến các toán tử nhị phân điển hình (và một hoặc hai hàm). +, -, * và tương tự. Đây là, đối với hầu hết các phần, khá tự giải thích 66Thực hiện bổ sung. 67Thực hiện phép trừ. 68Thực hiện phép nhân. 69 Thực hiện phép chia số nguyên bằng toán tử 00. 01 Thực hiện phép chia bằng toán tử 02. 03 Thực hiện phân chia thực sự. Lưu ý rằng điều này chỉ hoạt động khi 04 có hiệu lực. 05Thực hiện modulo sử dụng toán tử 06. 07Thực hiện hành vi cho phép chia dài bằng cách sử dụng chức năng tích hợp sẵn của 08. 09Thực hiện hành vi cho số mũ bằng cách sử dụng toán tử 10. 11 Thực hiện dịch chuyển bit trái bằng cách sử dụng toán tử 12. 13Thực hiện dịch chuyển bit sang phải bằng cách sử dụng toán tử 14. 15Thực hiện theo bit và sử dụng toán tử 16. 17Thực hiện theo bit hoặc sử dụng toán tử 18. 19Triển khai bitwise xor sử dụng toán tử 20Toán tử số học được phản ánhBạn có biết làm thế nào tôi nói rằng tôi sẽ phản ánh số học một chút không? . Nó thực sự khá đơn giản. Đây là một ví dụ 2Đó là phép cộng "bình thường". Tương đương được phản ánh là điều tương tự, ngoại trừ các toán hạng được chuyển đổi xung quanh 6Vì vậy, tất cả các phương thức ma thuật này đều thực hiện giống như các phương thức tương đương bình thường của chúng, ngoại trừ việc thực hiện thao tác với other là toán hạng đầu tiên và self là toán hạng thứ hai, thay vì ngược lại. Trong hầu hết các trường hợp, kết quả của một phép toán được phản ánh giống như phép toán tương đương thông thường của nó, vì vậy bạn có thể chỉ định nghĩa 21 là gọi 22, v.v. Lưu ý rằng đối tượng ở phía bên trái của toán tử ( 23 trong ví dụ) không được xác định (hoặc trả về 24) cho định nghĩa của nó về phiên bản không được phản ánh của một phép toán. Chẳng hạn, trong ví dụ này, 25 sẽ chỉ được gọi nếu 23 không định nghĩa 22 28Thực hiện bổ sung phản ánh. 29Thực hiện phép trừ phản ánh. 30Thực hiện phép nhân phản ánh. 31Thực hiện phép chia số nguyên được phản ánh bằng cách sử dụng toán tử 00. 33Thực hiện phép chia phản ánh bằng cách sử dụng toán tử 02. 35Thực hiện phản ánh sự phân chia thực sự. Lưu ý rằng điều này chỉ hoạt động khi 04 có hiệu lực. 37Triển khai modulo phản ánh bằng cách sử dụng toán tử 06. 39 Thực hiện hành vi cho phép chia dài bằng cách sử dụng chức năng tích hợp sẵn 08, khi 41 được gọi. 42Thực hiện hành vi cho số mũ được phản ánh bằng cách sử dụng toán tử 10. 44Các triển khai phản ánh dịch chuyển bit trái bằng cách sử dụng toán tử 12. 46Các triển khai phản ánh sự dịch chuyển theo chiều bit phải bằng cách sử dụng toán tử 14. 48Các triển khai được phản ánh theo bit và sử dụng toán tử 16. 50Các triển khai được phản ánh theo bit hoặc sử dụng toán tử 18. 52Implements phản ánh bitwise xor sử dụng toán tử 20bài tập tăng cườngPython cũng có nhiều phương thức ma thuật để cho phép xác định hành vi tùy chỉnh cho phép gán tăng cường. Có thể bạn đã quen thuộc với phép gán tăng cường, nó kết hợp các toán tử "bình thường" với phép gán. Nếu bạn vẫn không biết tôi đang nói về cái gì, thì đây là một ví dụ 5Mỗi phương thức này sẽ trả về giá trị mà biến ở phía bên trái sẽ được gán cho (ví dụ: đối với 54, 55 có thể trả về 56, giá trị này sẽ được gán cho 57). đây là danh sách 58Thực hiện phép cộng với phép gán. 59Thực hiện phép trừ với phép gán. 60Thực hiện phép nhân với phép gán. 61 Thực hiện phép chia số nguyên với phép gán bằng toán tử 62. 63 Thực hiện phép chia với phép gán bằng toán tử 64. 65Thực hiện phép chia đúng với phép gán. Lưu ý rằng điều này chỉ hoạt động khi 04 có hiệu lực. 67Triển khai modulo với phép gán sử dụng toán tử 68. 69Thực hiện hành vi cho số mũ với phép gán bằng cách sử dụng toán tử 70. 71Thực hiện dịch chuyển bit trái với phép gán bằng cách sử dụng toán tử 72. 73Thực hiện dịch chuyển theo chiều bit sang phải với phép gán bằng cách sử dụng toán tử 74. 75Thực hiện từng bit và với phép gán bằng toán tử 76. 77Triển khai bitwise hoặc gán bằng cách sử dụng toán tử 78. 79Triển khai bitwise xor với phép gán bằng toán tử 80Phương thức ma thuật chuyển đổi loạiPython cũng có một loạt các phương thức kỳ diệu được thiết kế để triển khai hành vi cho các hàm chuyển đổi kiểu tích hợp như 81. Họ đây rồi 82Thực hiện chuyển đổi loại thành int. 83Thực hiện chuyển đổi loại thành dài. 84Thực hiện chuyển đổi loại thành float. 85Thực hiện chuyển đổi loại thành phức tạp. 86Thực hiện chuyển đổi loại sang bát phân. 87Thực hiện chuyển đổi loại sang thập lục phân. 88Thực hiện chuyển đổi loại thành int khi đối tượng được sử dụng trong biểu thức lát. Nếu bạn xác định một loại số tùy chỉnh có thể được sử dụng trong việc cắt lát, bạn nên xác định 89. 64Được gọi khi 91 được gọi. 92 sẽ trả về giá trị của `self truncated thành một loại nguyên (thường là dài). 93Phương pháp thực hiện số học chế độ hỗn hợp. 94 sẽ trả về 95 nếu không thể chuyển đổi loại. Mặt khác, nó sẽ trả về một cặp (2-tuple) của 96 và 23, được thao tác để có cùng loạiThường rất hữu ích khi có một chuỗi biểu diễn của một lớp. Trong Python, có một số phương thức mà bạn có thể triển khai trong định nghĩa lớp của mình để tùy chỉnh cách các hàm tích hợp trả về các biểu diễn của hành vi lớp của bạn 98Xác định hành vi khi 99 được gọi trên một thể hiện của lớp của bạn. 00Xác định hành vi khi 01 được gọi trên một thể hiện của lớp học của bạn. Sự khác biệt chính giữa 99 và 01 là đối tượng mục tiêu. 01 nhằm mục đích tạo ra đầu ra hầu hết có thể đọc được bằng máy (trong nhiều trường hợp, nó thậm chí có thể là mã Python hợp lệ), trong khi 99 được dự định là người có thể đọc được. 06Xác định hành vi khi 07 được gọi trên một thể hiện của lớp học của bạn. 07 giống như 99, nhưng nó trả về một chuỗi unicode. hãy cảnh giác. nếu một khách hàng gọi 99 trên một phiên bản của lớp của bạn và bạn chỉ xác định 11, nó sẽ không hoạt động. Bạn cũng phải luôn cố gắng xác định 12 trong trường hợp ai đó không có điều kiện sử dụng unicode. 13Xác định hành vi khi một thể hiện của lớp của bạn được sử dụng trong định dạng chuỗi kiểu mới. Chẳng hạn, 14 sẽ dẫn đến cuộc gọi 15. Điều này có thể hữu ích để xác định các loại số hoặc chuỗi của riêng bạn mà bạn có thể muốn cung cấp các tùy chọn định dạng đặc biệt. 16Xác định hành vi khi 17 được gọi trên một thể hiện của lớp học của bạn. Nó phải trả về một số nguyên và kết quả của nó được sử dụng để so sánh khóa nhanh trong từ điển. Lưu ý rằng điều này thường đòi hỏi phải triển khai cả 27. Sống theo quy tắc sau. 19 ngụ ý 20. 21Xác định hành vi khi 22 được gọi trên một thể hiện của lớp học của bạn. Nên trả về 23 hoặc 24, tùy thuộc vào việc bạn muốn xem xét trường hợp là 23 hay 24. 27Xác định hành vi khi 28 được gọi trên một thể hiện của lớp học của bạn. Phương thức này sẽ trả về một danh sách các thuộc tính cho người dùng. Thông thường, việc triển khai 29 là không cần thiết, nhưng nó có thể cực kỳ quan trọng đối với việc sử dụng tương tác các lớp của bạn nếu bạn xác định lại 30 hoặc 31 (mà bạn sẽ thấy trong phần tiếp theo) hoặc nếu không thì đang tạo các thuộc tính động. 32Xác định hành vi khi 33 được gọi trên một thể hiện của lớp học của bạn. Điều này sẽ trả về kích thước của đối tượng của bạn, tính bằng byte. Điều này thường hữu ích hơn cho các lớp Python được triển khai trong các phần mở rộng C, nhưng nó giúp nhận thức được điều đóChúng ta đã hoàn thành khá nhiều phần nhàm chán (và không có ví dụ) của hướng dẫn phương pháp ma thuật. Bây giờ chúng ta đã đề cập đến một số phương pháp ma thuật cơ bản hơn, đã đến lúc chuyển sang tài liệu nâng cao hơn Nhiều người đến với Python từ các ngôn ngữ khác phàn nàn rằng nó thiếu khả năng đóng gói thực sự cho các lớp; . Điều này không thể xa hơn sự thật. điều xảy ra là Python hoàn thành rất nhiều việc đóng gói thông qua "phép thuật", thay vì các công cụ sửa đổi rõ ràng cho các phương thức hoặc trường. Hãy xem 34Bạn có thể xác định hành vi khi người dùng cố gắng truy cập một thuộc tính không tồn tại (hoặc chưa tồn tại). Điều này có thể hữu ích để nắm bắt và chuyển hướng các lỗi chính tả phổ biến, đưa ra cảnh báo về việc sử dụng các thuộc tính không dùng nữa (bạn vẫn có thể chọn tính toán và trả về thuộc tính đó nếu muốn) hoặc khéo léo trao một 35. Tuy nhiên, nó chỉ được gọi khi một thuộc tính không tồn tại được truy cập, vì vậy nó không phải là một giải pháp đóng gói thực sự. 36Không giống như 30, 38 là một giải pháp đóng gói. Nó cho phép bạn xác định hành vi gán cho một thuộc tính bất kể thuộc tính đó có tồn tại hay không, nghĩa là bạn có thể xác định quy tắc tùy chỉnh cho bất kỳ thay đổi nào trong giá trị của thuộc tính. Tuy nhiên, bạn phải cẩn thận với cách sử dụng 38, vì ví dụ ở cuối danh sách sẽ hiển thị. 40Điều này hoàn toàn giống với 38, nhưng để xóa các thuộc tính thay vì đặt chúng. Các biện pháp phòng ngừa tương tự cũng cần được thực hiện như với 38 để ngăn đệ quy vô hạn (gọi 43 trong quá trình triển khai 44 sẽ gây ra đệ quy vô hạn). 45Sau tất cả những điều này, 31 khá hòa hợp với những người bạn đồng hành của nó là 38 và 44. Tuy nhiên, tôi không khuyên bạn nên sử dụng nó. 31 chỉ có thể được sử dụng với các lớp kiểu mới (tất cả các lớp đều có kiểu mới trong các phiên bản Python mới nhất và trong các phiên bản cũ hơn, bạn có thể tạo một lớp kiểu mới bằng cách phân lớp 50. Nó cho phép bạn xác định quy tắc bất cứ khi nào giá trị của thuộc tính được truy cập. Nó gặp phải một số vấn đề về đệ quy vô hạn tương tự như đối tác của nó (lần này bạn gọi phương thức 31 của lớp cơ sở để ngăn chặn điều này). Nó cũng chủ yếu làm giảm nhu cầu về 30, khi 31 được triển khai, chỉ được gọi nếu nó được gọi rõ ràng hoặc một 35 được nâng lên. Phương pháp này có thể được sử dụng (xét cho cùng, đó là lựa chọn của bạn), nhưng tôi không khuyên dùng phương pháp này vì nó có một trường hợp sử dụng nhỏ (rất hiếm khi chúng ta cần hành vi đặc biệt để truy xuất một giá trị hơn là gán cho nó) và bởi vì Bạn có thể dễ dàng gây ra sự cố trong định nghĩa của mình về bất kỳ phương thức nào kiểm soát quyền truy cập thuộc tính. Hãy xem xét ví dụ này 7Một lần nữa, các phương pháp ma thuật của Python vô cùng mạnh mẽ và sức mạnh to lớn đi kèm với trách nhiệm lớn. Điều quan trọng là phải biết cách thích hợp để sử dụng các phương pháp ma thuật để bạn không vi phạm bất kỳ mã nào Vì vậy, chúng ta đã học được gì về quyền truy cập thuộc tính tùy chỉnh trong Python? . Trên thực tế, nó có xu hướng quá mạnh và phản trực giác. Nhưng sở dĩ nó tồn tại là để gãi đúng chỗ ngứa. Python không tìm cách biến những điều tồi tệ thành không thể, mà chỉ làm cho chúng trở nên khó khăn. Tự do là tối quan trọng, vì vậy bạn thực sự có thể làm bất cứ điều gì bạn muốn. Dưới đây là ví dụ về một số phương thức truy cập thuộc tính đặc biệt đang hoạt động (lưu ý rằng chúng tôi sử dụng 55 vì không phải tất cả các lớp đều có thuộc tính 56) 6Có một số cách để khiến các lớp Python của bạn hoạt động giống như các chuỗi được tạo sẵn ( 57, 58, 59, 73, v.v. ). Cho đến nay, đây là những phương thức ma thuật yêu thích của tôi trong Python vì mức độ kiểm soát vô lý mà chúng mang lại cho bạn và cách mà chúng làm cho toàn bộ một mảng các hàm toàn cục hoạt động một cách tuyệt vời trên các thể hiện của lớp của bạn một cách kỳ diệu. Nhưng trước khi chúng ta chuyển sang nội dung hay, nói nhanh về các yêu cầuYêu cầuBây giờ chúng ta đang nói về việc tạo các chuỗi của riêng bạn trong Python, đã đến lúc nói về các giao thức. Các giao thức hơi giống với các giao diện trong các ngôn ngữ khác ở chỗ chúng cung cấp cho bạn một tập hợp các phương thức mà bạn phải xác định. Tuy nhiên, trong các giao thức Python hoàn toàn không chính thức và không yêu cầu khai báo rõ ràng để thực hiện. Thay vào đó, chúng giống như hướng dẫn hơn Tại sao bây giờ chúng ta lại nói về các giao thức? . Đầu tiên, có giao thức để xác định các thùng chứa bất biến. để tạo một vùng chứa bất biến, bạn chỉ cần xác định 61 và 62 (thêm về những điều này sau). Giao thức vùng chứa có thể thay đổi yêu cầu mọi thứ mà vùng chứa bất biến yêu cầu cộng với 63 và 64. Cuối cùng, nếu bạn muốn đối tượng của mình có thể lặp lại, bạn sẽ phải xác định 65, trả về một trình vòng lặp. Iterator đó phải tuân thủ một giao thức iterator, giao thức này yêu cầu iterator phải có các phương thức gọi là 65(trả về chính nó) và 67Điều kỳ diệu đằng sau những chiếc containerCòn chần chờ gì nữa, đây là những phương pháp kỳ diệu mà container sử dụng 68Trả về chiều dài của container. Một phần của giao thức cho cả vùng chứa bất biến và có thể thay đổi. 69Xác định hành vi khi một mục được truy cập, sử dụng ký hiệu 70. Đây cũng là một phần của cả giao thức vùng chứa có thể thay đổi và không thể thay đổi. Nó cũng nên đưa ra các ngoại lệ thích hợp. 71 nếu loại khóa sai và 72 nếu không có giá trị tương ứng cho khóa. 73Xác định hành vi khi một mục được gán cho, sử dụng ký hiệu 74. Đây là một phần của giao thức vùng chứa có thể thay đổi. Một lần nữa, bạn nên tăng 72 và 71 khi thích hợp. 77Xác định hành vi khi một mục bị xóa (e. g. 78). Đây chỉ là một phần của giao thức vùng chứa có thể thay đổi. Bạn phải đưa ra các ngoại lệ thích hợp khi sử dụng khóa không hợp lệ. 79Nên trả về một trình vòng lặp cho vùng chứa. Các trình vòng lặp được trả về trong một số ngữ cảnh, đáng chú ý nhất là hàm tích hợp sẵn của 80 và khi một vùng chứa được lặp lại bằng cách sử dụng biểu mẫu 81. Trình vòng lặp là đối tượng của riêng chúng và chúng cũng phải xác định một phương thức 65 trả về 96. 84Được gọi để thực hiện hành vi cho chức năng tích hợp sẵn của 85. Nên trả về một phiên bản đảo ngược của trình tự. Chỉ thực hiện điều này nếu lớp trình tự được sắp xếp, như danh sách hoặc tuple. 86 87 xác định hành vi cho các bài kiểm tra tư cách thành viên bằng cách sử dụng 88 và 89. Bạn hỏi tại sao đây không phải là một phần của giao thức trình tự? . 92 93 được sử dụng trong các lớp con của 57. Nó xác định hành vi cho bất cứ khi nào một khóa được truy cập không tồn tại trong từ điển (ví dụ: nếu tôi có một từ điển 95 và nói 96 khi 97 không phải là khóa trong chính tả, thì 98 sẽ được gọi)Một ví dụVí dụ của chúng tôi, hãy xem danh sách triển khai một số cấu trúc chức năng mà bạn có thể quen dùng từ các ngôn ngữ khác (ví dụ: Haskell) 6Bạn đã có nó, một ví dụ hữu ích (không đáng kể) về cách triển khai trình tự của riêng bạn. Tất nhiên, có nhiều ứng dụng hữu ích hơn của trình tự tùy chỉnh, nhưng khá nhiều trong số chúng đã được triển khai trong thư viện tiêu chuẩn (bao gồm cả pin, phải không?), như 99, 200 và 201Bạn cũng có thể kiểm soát cách phản chiếu bằng cách sử dụng các hàm tích hợp sẵn 202 và 203 hoạt động bằng cách xác định các phương thức ma thuật. Các phương pháp ma thuật là 204Kiểm tra xem một thể hiện có phải là một thể hiện của lớp bạn đã xác định không (e. g. 205. 206Kiểm tra xem một lớp có phân lớp lớp bạn đã xác định không (e. g. 207)Trường hợp sử dụng cho các phương pháp ma thuật này có vẻ nhỏ và điều đó rất có thể đúng. Tôi sẽ không dành quá nhiều thời gian cho các phương thức ma thuật phản chiếu vì chúng không quan trọng lắm, nhưng chúng phản ánh một điều quan trọng về lập trình hướng đối tượng trong Python và Python nói chung. hầu như luôn có một cách dễ dàng để làm điều gì đó, ngay cả khi điều đó hiếm khi cần thiết. Những phương pháp ma thuật này có vẻ không hữu ích, nhưng nếu bạn cần chúng, bạn sẽ rất vui vì chúng ở đó (và bạn đã đọc hướng dẫn này. ) Như bạn có thể đã biết, trong Python, hàm là đối tượng hạng nhất. Điều này có nghĩa là chúng có thể được truyền cho các hàm và phương thức như thể chúng là các đối tượng thuộc bất kỳ loại nào khác. Đây là một tính năng vô cùng mạnh mẽ Một phương thức ma thuật đặc biệt trong Python cho phép các thể hiện của các lớp của bạn hoạt động như thể chúng là các hàm, do đó bạn có thể "gọi" chúng, chuyển chúng tới các hàm lấy các hàm làm đối số, v.v. Đây là một tính năng tiện lợi mạnh mẽ khác giúp lập trình bằng Python trở nên dễ dàng hơn nhiều 208Cho phép một thể hiện của một lớp được gọi là một hàm. Về cơ bản, điều này có nghĩa là 209 giống như 210. Lưu ý rằng 211 có số lượng đối số thay đổi; 211 có thể đặc biệt hữu ích trong các lớp có các thể hiện thường xuyên thay đổi trạng thái. "Gọi" thể hiện có thể là một cách trực quan và tao nhã để thay đổi trạng thái của đối tượng. Một ví dụ có thể là một lớp đại diện cho vị trí của một thực thể trên một mặt phẳng 0Trong Python 2. 5, một từ khóa mới đã được giới thiệu trong Python cùng với một phương pháp mới để tái sử dụng mã. tuyên bố 214. Khái niệm về trình quản lý bối cảnh hầu như không mới trong Python (nó đã được triển khai trước đây như một phần của thư viện), nhưng phải đến khi PEP 343 được chấp nhận, nó mới đạt được trạng thái là cấu trúc ngôn ngữ hạng nhất. Bạn có thể đã thấy các câu lệnh của 214 trước đây 1Trình quản lý ngữ cảnh cho phép thực hiện các hành động thiết lập và dọn dẹp đối tượng khi quá trình tạo của chúng được bao bọc bằng câu lệnh 214. Hành vi của trình quản lý bối cảnh được xác định bởi hai phương thức ma thuật 217Xác định những gì trình quản lý bối cảnh nên làm khi bắt đầu khối được tạo bởi câu lệnh 214. Lưu ý rằng giá trị trả về của 219 bị ràng buộc với đích của câu lệnh 214 hoặc tên sau 221. 222Xác định những gì trình quản lý bối cảnh nên làm sau khi khối của nó được thực thi (hoặc chấm dứt). Nó có thể được sử dụng để xử lý các ngoại lệ, thực hiện dọn dẹp hoặc làm điều gì đó luôn được thực hiện ngay sau hành động trong khối. Nếu khối thực thi thành công, 223, 224 và 225 sẽ là 95. Nếu không, bạn có thể chọn xử lý ngoại lệ hoặc để người dùng xử lý; . Nếu bạn không muốn trình quản lý bối cảnh xử lý ngoại lệ, hãy để nó xảy ra 219 và 227 có thể hữu ích cho các lớp cụ thể có hành vi phổ biến và được xác định rõ để thiết lập và dọn dẹp. Bạn cũng có thể sử dụng các phương thức này để tạo trình quản lý ngữ cảnh chung bao bọc các đối tượng khác. Đây là một ví dụ 2Đây là một ví dụ về hoạt động của 231, sử dụng kết nối FTP để chứng minh điều đó (ổ cắm có thể đóng được) 3Xem cách trình bao bọc của chúng tôi xử lý khéo léo cả việc sử dụng hợp lý và không hợp lệ? . Lưu ý rằng thư viện chuẩn của Python bao gồm một contextlib mô-đun chứa trình quản lý ngữ cảnh, 232, thực hiện gần giống như vậy (không có bất kỳ xử lý nào đối với trường hợp một đối tượng không có phương thức 233)xem http. // tài liệu. con trăn. org/2/thư viện/abc. html Các bộ mô tả là các lớp, khi được truy cập thông qua nhận, đặt hoặc xóa, cũng có thể thay đổi các đối tượng khác. Các mô tả không có nghĩa là đứng một mình; . Các bộ mô tả có thể hữu ích khi xây dựng cơ sở dữ liệu hướng đối tượng hoặc các lớp có các thuộc tính có giá trị phụ thuộc lẫn nhau. Các bộ mô tả đặc biệt hữu ích khi biểu diễn các thuộc tính trong một số đơn vị đo lường khác nhau hoặc biểu thị các thuộc tính được tính toán (như khoảng cách từ gốc trong một lớp để biểu thị một điểm trên lưới) Để trở thành một bộ mô tả, một lớp phải có ít nhất một trong số 234, 235 và 236 được triển khai. Hãy cùng điểm qua những phương pháp thần kỳ đó nhé 237Xác định hành vi khi giá trị của bộ mô tả được truy xuất. 238 là thể hiện của đối tượng chủ sở hữu. 239 chính là lớp chủ sở hữu. 240Xác định hành vi khi giá trị của bộ mô tả bị thay đổi. 238 là thể hiện của lớp chủ sở hữu và 242 là giá trị để đặt bộ mô tả thành. 243Xác định hành vi khi giá trị của bộ mô tả bị xóa. 238 là thể hiện của đối tượng chủ sở hữuBây giờ, một ví dụ về ứng dụng hữu ích của bộ mô tả. chuyển đổi đơn vị 4Đôi khi, đặc biệt là khi xử lý các đối tượng có thể thay đổi, bạn muốn có thể sao chép một đối tượng và thực hiện các thay đổi mà không ảnh hưởng đến những gì bạn đã sao chép từ đó. Đây là lúc 245 của Python phát huy tác dụng. Tuy nhiên (may mắn thay), các mô-đun Python không có tri giác, vì vậy chúng ta không phải lo lắng về sự nổi dậy của rô-bốt dựa trên Linux, nhưng chúng ta phải cho Python biết cách sao chép mọi thứ một cách hiệu quả 246Xác định hành vi cho 247 đối với các phiên bản của lớp học của bạn. 247 trả về một bản sao nông của đối tượng -- điều này có nghĩa là, trong khi bản thân thể hiện là một thể hiện mới, tất cả dữ liệu của nó được tham chiếu -- tôi. e. , bản thân đối tượng được sao chép, nhưng dữ liệu của nó vẫn được tham chiếu (và do đó những thay đổi đối với dữ liệu trong một bản sao nông có thể gây ra những thay đổi trong bản gốc). 249Xác định hành vi cho 250 đối với các phiên bản của lớp học của bạn. 250 trả về một bản sao sâu đối tượng của bạn -- cả đối tượng và dữ liệu của nó đều được sao chép. 252 là bộ đệm của các đối tượng đã sao chép trước đó -- điều này tối ưu hóa việc sao chép và ngăn chặn đệ quy vô hạn khi sao chép cấu trúc dữ liệu đệ quy. Khi bạn muốn sao chép sâu một thuộc tính riêng lẻ, hãy gọi 250 trên thuộc tính đó với 252 làm đối số đầu tiênMột số trường hợp sử dụng cho các phương pháp ma thuật này là gì? . Ví dụ: nếu bạn đang cố gắng sao chép một đối tượng lưu trữ bộ nhớ cache dưới dạng từ điển (có thể lớn), thì việc sao chép bộ nhớ cache cũng không hợp lý -- nếu bộ nhớ cache có thể được chia sẻ trong bộ nhớ giữa các phiên bản, thì Nếu bạn dành thời gian với các Pythonistas khác, rất có thể bạn ít nhất đã nghe nói về dưa chua. Pickling là một quy trình tuần tự hóa cho các cấu trúc dữ liệu Python và có thể cực kỳ hữu ích khi bạn cần lưu trữ một đối tượng và truy xuất nó sau này (thường là để lưu vào bộ nhớ đệm). Nó cũng là một nguồn chính của lo lắng và nhầm lẫn Pickling quan trọng đến mức nó không chỉ có mô-đun riêng ( 255), mà còn có giao thức riêng và các phương pháp kỳ diệu đi kèm với nó. Nhưng trước tiên, một lời ngắn gọn về cách chọn các loại hiện có (vui lòng bỏ qua nếu bạn đã biết)muối chua. Ngâm nhanh trong nước muốiHãy đi sâu vào dưa chua. Giả sử bạn có một từ điển mà bạn muốn lưu trữ và truy xuất sau. Bạn có thể viết nội dung của nó vào một tệp, cẩn thận đảm bảo rằng bạn viết đúng cú pháp, sau đó truy xuất nó bằng cách sử dụng 256 hoặc xử lý đầu vào tệp. Nhưng điều này là bấp bênh nhất. nếu bạn lưu trữ dữ liệu quan trọng ở dạng văn bản thuần túy, dữ liệu đó có thể bị hỏng hoặc bị thay đổi theo bất kỳ cách nào khiến chương trình của bạn gặp sự cố hoặc tệ hơn là chạy mã độc trên máy tính của bạn. Thay vào đó, chúng ta sẽ ngâm nó 5Bây giờ, vài giờ sau, chúng tôi muốn lấy lại. Tất cả những gì chúng ta phải làm là giải nén nó 6Điều gì xảy ra? . Nó giống như chúng ta đã có 257 trong suốt thời gian quaBây giờ, cho một lời cảnh báo. dưa chua không hoàn hảo. Các tệp dưa chua dễ dàng bị hỏng do vô tình hoặc có mục đích. Pickling có thể an toàn hơn so với sử dụng tệp văn bản phẳng, nhưng nó vẫn có thể được sử dụng để chạy mã độc. Nó cũng không tương thích giữa các phiên bản Python khác nhau, vì vậy đừng mong đợi phân phối các đối tượng được chọn và mong mọi người có thể mở chúng. Tuy nhiên, nó cũng có thể là một công cụ mạnh để tạo bộ nhớ đệm và các tác vụ tuần tự hóa phổ biến khác Chọn đối tượng của riêng bạnPickling không chỉ dành cho các loại tích hợp. Nó dành cho bất kỳ lớp nào tuân theo giao thức dưa chua. Giao thức dưa chua có bốn phương thức tùy chọn cho các đối tượng Python để tùy chỉnh cách chúng hoạt động (hơi khác một chút đối với các phần mở rộng C, nhưng điều đó không thuộc phạm vi của chúng tôi) 258Nếu bạn muốn 8 được gọi khi lớp của bạn chưa được chọn, bạn có thể định nghĩa 260, nó sẽ trả về một bộ các đối số mà bạn muốn được chuyển đến 8. Lưu ý rằng phương pháp này sẽ chỉ hoạt động đối với các lớp kiểu cũ. 262Đối với các lớp kiểu mới, bạn có thể tác động đến những đối số nào được chuyển đến 3 khi bỏ chọn. Phương thức này cũng sẽ trả về một bộ đối số mà sau đó sẽ được chuyển đến 3. 265Thay vì thuộc tính 56 của đối tượng được lưu trữ, bạn có thể trả về trạng thái tùy chỉnh sẽ được lưu trữ khi đối tượng được chọn. Trạng thái đó sẽ được sử dụng bởi 267 khi đối tượng được giải nén. 268Khi đối tượng được giải nén, nếu 267 được xác định thì trạng thái của đối tượng sẽ được truyền cho nó thay vì áp dụng trực tiếp cho 56 của đối tượng. Điều này đi đôi với 271. khi cả hai được xác định, bạn có thể biểu diễn trạng thái ngâm của đối tượng theo cách bạn muốn với bất kỳ thứ gì bạn muốn. 272Khi xác định các loại tiện ích mở rộng (i. e. , các loại được triển khai bằng API C của Python), bạn phải cho Python biết cách loại bỏ chúng nếu bạn muốn chúng loại bỏ chúng. 273 được gọi khi một đối tượng xác định nó được chọn. Nó có thể trả về một chuỗi đại diện cho một tên chung mà Python sẽ tra cứu và chọn hoặc một bộ dữ liệu. Tuple chứa từ 2 đến 5 phần tử. một đối tượng có thể gọi được được gọi để tạo lại đối tượng, một bộ đối số cho đối tượng có thể gọi đó, trạng thái được chuyển đến 267 (tùy chọn), một trình vòng lặp mang lại các mục danh sách sẽ được chọn (tùy chọn) và một trình vòng lặp mang lại các mục từ điển là . 275 276 tồn tại để tương thích. Nếu nó được xác định, 276 sẽ được gọi trên 278 khi ngâm. 278 cũng có thể được xác định cho các phiên bản cũ hơn của API tẩy không hỗ trợ 276Một ví dụVí dụ của chúng tôi là một 281, ghi nhớ các giá trị của nó là gì và khi các giá trị đó được ghi vào nó. Tuy nhiên, phương tiện cụ thể này sẽ trống mỗi khi nó được ngâm. giá trị hiện tại sẽ không được lưu 7Mục tiêu của hướng dẫn này là mang lại điều gì đó cho bất kỳ ai đọc nó, bất kể kinh nghiệm của họ với Python hay lập trình hướng đối tượng. Nếu bạn mới bắt đầu với Python, thì bạn đã có được kiến thức quý giá về kiến thức cơ bản để viết các lớp giàu tính năng, trang nhã và dễ sử dụng. Nếu bạn là một lập trình viên Python trung cấp, có lẽ bạn đã học được một số khái niệm và chiến lược mới và một số cách hay để giảm lượng mã do bạn và khách hàng viết. Nếu bạn là một Pythonista lão luyện, bạn đã được làm mới một số nội dung mà bạn có thể đã quên và có thể học được một vài thủ thuật mới trong quá trình thực hiện. Dù kinh nghiệm của bạn ở cấp độ nào, tôi hy vọng rằng chuyến đi thông qua các phương pháp đặc biệt của Python này thực sự kỳ diệu. (Tôi không thể cưỡng lại cách chơi chữ cuối cùng. ) Một số phương thức ma thuật trong Python ánh xạ trực tiếp tới các hàm dựng sẵn; . Tuy nhiên, trong các trường hợp khác, lời kêu gọi ít rõ ràng hơn nhiều. Phụ lục này được dành để phơi bày cú pháp không rõ ràng dẫn đến các phương thức ma thuật được gọi Phương thức ma thuật Khi nó được gọi (ví dụ)Giải thích 282 283 3 được gọi khi tạo cá thể 285 283 8 được gọi khi tạo cá thể 28 62, 63, v.v. Called for any comparison 79 292Unary plus sign 61 294Unary minus sign 65 296Bitwise inversion 88 298Conversion when object is used as index 21 200Boolean value of the object 34 202Accessing nonexistent attribute 203 204Assigning to an attribute 40 43Deleting an attribute 45 208Accessing any attribute 69 70Accessing an item using an index 211 212Assigning to an item using an index 77 78Deleting an item using an index 79 216Iteration 217 218, 219Membership tests using 88 221 222" Hy vọng rằng, bảng này sẽ giải đáp mọi thắc mắc của bạn về cú pháp nào gọi phương thức ma thuật nào |