Đố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.

if instance.equals(other_instance):
    # do something
8 hoặc
if instance.equals(other_instance):
    # do something
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,

if instance.equals(other_instance):
    # do something
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
if instance == other_instance:
    #do something
1,
if instance.equals(other_instance):
    # do something
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à
if instance == other_instance:
    #do something
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ó
if instance == other_instance:
    #do something
4. Hãy cùng tìm hiểu kỹ hơn về 3 phương pháp kỳ diệu này

if instance == other_instance:
    #do something
5
if instance == other_instance:
    #do something
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
if instance.equals(other_instance):
    # do something
8.
if instance == other_instance:
    #do something
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ề
if instance == other_instance:
    #do something
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.
if instance.equals(other_instance):
    # do something
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à
if instance.equals(other_instance):
    # do something
21, thì
if instance.equals(other_instance):
    # do something
8 sẽ được truyền là
if instance.equals(other_instance):
    # do something
23 và
if instance.equals(other_instance):
    # do something
24 làm đối số.
if instance.equals(other_instance):
    # do something
8 hầu như được sử dụng phổ biến trong các định nghĩa lớp Python.
if instance.equals(other_instance):
    # do something
26Nếu
if instance == other_instance:
    #do something
3 và
if instance.equals(other_instance):
    # do something
8 tạo thành hàm tạo của đối tượng, thì
if instance == other_instance:
    #do something
4 là hàm hủy. Nó không triển khai hành vi cho câu lệnh
if instance.equals(other_instance):
    # do something
20 (do đó mã sẽ không dịch thành
if instance.equals(other_instance):
    # do something
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
if instance == other_instance:
    #do something
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 đó,
if instance == other_instance:
    #do something
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ế,
if instance == other_instance:
    #do something
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

if instance.equals(other_instance):
    # do something
8 và
if instance == other_instance:
    #do something
4

if instance.equals(other_instance):
    # do something
9

Mộ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

if instance.equals(other_instance):
    # do something

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

if instance == other_instance:
    #do something

Đó 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

if instance.equals(other_instance):
    # do something
28
if instance.equals(other_instance):
    # do something
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).
if instance.equals(other_instance):
    # do something
29 sẽ trả về một số nguyên âm nếu
if instance == other_instance:
    #do something
61, 0 nếu
if instance == other_instance:
    #do something
62 và dương nếu
if instance == other_instance:
    #do something
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
if instance.equals(other_instance):
    # do something
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ự.
if instance == other_instance:
    #do something
65Xác định hành vi cho toán tử bình đẳng,
if instance == other_instance:
    #do something
66.
if instance == other_instance:
    #do something
67Xác định hành vi cho toán tử bất đẳng thức,
if instance == other_instance:
    #do something
68.
if instance == other_instance:
    #do something
69Xác định hành vi cho toán tử nhỏ hơn,
if instance.equals(other_instance):
    # do something
50.
if instance.equals(other_instance):
    # do something
51Xác định hành vi cho toán tử lớn hơn,
if instance.equals(other_instance):
    # do something
52.
if instance.equals(other_instance):
    # do something
53Xác định hành vi cho toán tử nhỏ hơn hoặc bằng,
if instance.equals(other_instance):
    # do something
54. ________ 455 Xác định hành vi cho toán tử lớn hơn hoặc bằng, ________ 456

Ví 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

if instance.equals(other_instance):
    # do something
2

Bây giờ, chúng ta có thể tạo hai

if instance.equals(other_instance):
    # do something
57 (bằng cách sử dụng
if instance.equals(other_instance):
    # do something
58 và
if instance.equals(other_instance):
    # do something
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
if instance.equals(other_instance):
    # do something
27 và
if instance == other_instance:
    #do something
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à
if instance == other_instance:
    #do something
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
if instance == other_instance:
    #do something
73

Bâ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

if instance == other_instance:
    #do something
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
if instance.equals(other_instance):
    # do something
27 và một phương thức khác (e. g.
if instance == other_instance:
    #do something
76,
if instance.equals(other_instance):
    # do something
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
if instance == other_instance:
    #do something
78 phía trên định nghĩa lớp của bạn

Giố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ôi

Cá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.

if instance == other_instance:
    #do something
79Thực hiện hành vi cho tích cực đơn phương (e. g.
if instance == other_instance:
    #do something
60)
if instance == other_instance:
    #do something
61Thực hiện hành vi phủ định (e. g.
if instance == other_instance:
    #do something
62)
if instance == other_instance:
    #do something
63Thực hiện hành vi cho chức năng
if instance == other_instance:
    #do something
64 tích hợp.
if instance == other_instance:
    #do something
65Thực hiện hành vi để đảo ngược bằng cách sử dụng toán tử
if instance == other_instance:
    #do something
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.
if instance == other_instance:
    #do something
67Triển khai hành vi cho hàm
if instance == other_instance:
    #do something
68 tích hợp.
if instance == other_instance:
    #do something
69 là số chữ số thập phân cần làm tròn đến.
if instance == other_instance:
    #do something
60Thực hiện hành vi cho
if instance == other_instance:
    #do something
61, i. e. , làm tròn xuống số nguyên gần nhất.
if instance == other_instance:
    #do something
62Thực hiện hành vi cho
if instance == other_instance:
    #do something
63, tôi. e. , làm tròn lên đến số nguyên gần nhất.
if instance == other_instance:
    #do something
64Thực hiện hành vi cho
if instance == other_instance:
    #do something
65, i. e. , rút ​​gọn thành tích phân

Toán tử số học bình thường

Bâ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

if instance == other_instance:
    #do something
66Thực hiện bổ sung.
if instance == other_instance:
    #do something
67Thực hiện phép trừ.
if instance == other_instance:
    #do something
68Thực hiện phép nhân.
if instance == other_instance:
    #do something
69 Thực hiện phép chia số nguyên bằng toán tử
if instance.equals(other_instance):
    # do something
00.
if instance.equals(other_instance):
    # do something
01 Thực hiện phép chia bằng toán tử
if instance.equals(other_instance):
    # do something
02.
if instance.equals(other_instance):
    # do something
03 Thực hiện phân chia thực sự. Lưu ý rằng điều này chỉ hoạt động khi
if instance.equals(other_instance):
    # do something
04 có hiệu lực.
if instance.equals(other_instance):
    # do something
05Thực hiện modulo sử dụng toán tử
if instance.equals(other_instance):
    # do something
06.
if instance.equals(other_instance):
    # do something
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
if instance.equals(other_instance):
    # do something
08.
if instance.equals(other_instance):
    # do something
09Thực hiện hành vi cho số mũ bằng cách sử dụng toán tử
if instance.equals(other_instance):
    # do something
10.
if instance.equals(other_instance):
    # do something
11 Thực hiện dịch chuyển bit trái bằng cách sử dụng toán tử
if instance.equals(other_instance):
    # do something
12.
if instance.equals(other_instance):
    # do something
13Thực hiện dịch chuyển bit sang phải bằng cách sử dụng toán tử
if instance.equals(other_instance):
    # do something
14.
if instance.equals(other_instance):
    # do something
15Thực hiện theo bit và sử dụng toán tử
if instance.equals(other_instance):
    # do something
16.
if instance.equals(other_instance):
    # do something
17Thực hiện theo bit hoặc sử dụng toán tử
if instance.equals(other_instance):
    # do something
18.
if instance.equals(other_instance):
    # do something
19Triển khai bitwise xor sử dụng toán tử
if instance.equals(other_instance):
    # do something
20

Toán tử số học được phản ánh

Bạ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ụ

if instance.equals(other_instance):
    # do something
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

if instance == other_instance:
    #do something
6

Vì 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

if instance.equals(other_instance):
    # do something
21 là gọi
if instance.equals(other_instance):
    # do something
22, v.v. Lưu ý rằng đối tượng ở phía bên trái của toán tử (
if instance.equals(other_instance):
    # do something
23 trong ví dụ) không được xác định (hoặc trả về
if instance.equals(other_instance):
    # do something
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,
if instance.equals(other_instance):
    # do something
25 sẽ chỉ được gọi nếu
if instance.equals(other_instance):
    # do something
23 không định nghĩa
if instance.equals(other_instance):
    # do something
22

if instance.equals(other_instance):
    # do something
28Thực hiện bổ sung phản ánh.
if instance.equals(other_instance):
    # do something
29Thực hiện phép trừ phản ánh.
if instance.equals(other_instance):
    # do something
30Thực hiện phép nhân phản ánh.
if instance.equals(other_instance):
    # do something
31Thực hiện phép chia số nguyên được phản ánh bằng cách sử dụng toán tử
if instance.equals(other_instance):
    # do something
00.
if instance.equals(other_instance):
    # do something
33Thực hiện phép chia phản ánh bằng cách sử dụng toán tử
if instance.equals(other_instance):
    # do something
02.
if instance.equals(other_instance):
    # do something
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
if instance.equals(other_instance):
    # do something
04 có hiệu lực.
if instance.equals(other_instance):
    # do something
37Triển khai modulo phản ánh bằng cách sử dụng toán tử
if instance.equals(other_instance):
    # do something
06.
if instance.equals(other_instance):
    # do something
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
if instance.equals(other_instance):
    # do something
08, khi
if instance.equals(other_instance):
    # do something
41 được gọi.
if instance.equals(other_instance):
    # do something
42Thực hiện hành vi cho số mũ được phản ánh bằng cách sử dụng toán tử
if instance.equals(other_instance):
    # do something
10.
if instance.equals(other_instance):
    # do something
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ử
if instance.equals(other_instance):
    # do something
12.
if instance.equals(other_instance):
    # do something
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ử
if instance.equals(other_instance):
    # do something
14.
if instance.equals(other_instance):
    # do something
48Các triển khai được phản ánh theo bit và sử dụng toán tử
if instance.equals(other_instance):
    # do something
16.
if instance.equals(other_instance):
    # do something
50Các triển khai được phản ánh theo bit hoặc sử dụng toán tử
if instance.equals(other_instance):
    # do something
18.
if instance.equals(other_instance):
    # do something
52Implements phản ánh bitwise xor sử dụng toán tử
if instance.equals(other_instance):
    # do something
20

bài tập tăng cường

Python 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ụ

if instance.equals(other_instance):
    # do something
5

Mỗ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

if instance.equals(other_instance):
    # do something
54,
if instance.equals(other_instance):
    # do something
55 có thể trả về
if instance.equals(other_instance):
    # do something
56, giá trị này sẽ được gán cho
if instance.equals(other_instance):
    # do something
57). đây là danh sách

if instance.equals(other_instance):
    # do something
58Thực hiện phép cộng với phép gán.
if instance.equals(other_instance):
    # do something
59Thực hiện phép trừ với phép gán.
if instance.equals(other_instance):
    # do something
60Thực hiện phép nhân với phép gán.
if instance.equals(other_instance):
    # do something
61 Thực hiện phép chia số nguyên với phép gán bằng toán tử
if instance.equals(other_instance):
    # do something
62.
if instance.equals(other_instance):
    # do something
63 Thực hiện phép chia với phép gán bằng toán tử
if instance.equals(other_instance):
    # do something
64.
if instance.equals(other_instance):
    # do something
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
if instance.equals(other_instance):
    # do something
04 có hiệu lực.
if instance.equals(other_instance):
    # do something
67Triển khai modulo với phép gán sử dụng toán tử
if instance.equals(other_instance):
    # do something
68.
if instance.equals(other_instance):
    # do something
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ử
if instance.equals(other_instance):
    # do something
70.
if instance.equals(other_instance):
    # do something
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ử
if instance.equals(other_instance):
    # do something
72.
if instance.equals(other_instance):
    # do something
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ử
if instance.equals(other_instance):
    # do something
74.
if instance.equals(other_instance):
    # do something
75Thực hiện từng bit và với phép gán bằng toán tử
if instance.equals(other_instance):
    # do something
76.
if instance.equals(other_instance):
    # do something
77Triển khai bitwise hoặc gán bằng cách sử dụng toán tử
if instance.equals(other_instance):
    # do something
78.
if instance.equals(other_instance):
    # do something
79Triển khai bitwise xor với phép gán bằng toán tử
if instance.equals(other_instance):
    # do something
80

Phương thức ma thuật chuyển đổi loại

Python 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ư

if instance.equals(other_instance):
    # do something
81. Họ đây rồi

if instance.equals(other_instance):
    # do something
82Thực hiện chuyển đổi loại thành int.
if instance.equals(other_instance):
    # do something
83Thực hiện chuyển đổi loại thành dài.
if instance.equals(other_instance):
    # do something
84Thực hiện chuyển đổi loại thành float.
if instance.equals(other_instance):
    # do something
85Thực hiện chuyển đổi loại thành phức tạp.
if instance.equals(other_instance):
    # do something
86Thực hiện chuyển đổi loại sang bát phân.
if instance.equals(other_instance):
    # do something
87Thực hiện chuyển đổi loại sang thập lục phân.
if instance.equals(other_instance):
    # do something
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
if instance.equals(other_instance):
    # do something
89.
if instance == other_instance:
    #do something
64Được gọi khi
if instance.equals(other_instance):
    # do something
91 được gọi.
if instance.equals(other_instance):
    # do something
92 sẽ trả về giá trị của `self truncated thành một loại nguyên (thường là dài).
if instance.equals(other_instance):
    # do something
93Phương pháp thực hiện số học chế độ hỗn hợp.
if instance.equals(other_instance):
    # do something
94 sẽ trả về
if instance.equals(other_instance):
    # do something
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
if instance.equals(other_instance):
    # do something
96 và
if instance.equals(other_instance):
    # do something
23, được thao tác để có cùng loại

Thườ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

if instance.equals(other_instance):
    # do something
98Xác định hành vi khi
if instance.equals(other_instance):
    # do something
99 được gọi trên một thể hiện của lớp của bạn.
if instance == other_instance:
    #do something
00Xác định hành vi khi
if instance == other_instance:
    #do something
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
if instance.equals(other_instance):
    # do something
99 và
if instance == other_instance:
    #do something
01 là đối tượng mục tiêu.
if instance == other_instance:
    #do something
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
if instance.equals(other_instance):
    # do something
99 được dự định là người có thể đọc được.
if instance == other_instance:
    #do something
06Xác định hành vi khi
if instance == other_instance:
    #do something
07 được gọi trên một thể hiện của lớp học của bạn.
if instance == other_instance:
    #do something
07 giống như
if instance.equals(other_instance):
    # do something
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
if instance.equals(other_instance):
    # do something
99 trên một phiên bản của lớp của bạn và bạn chỉ xác định
if instance == other_instance:
    #do something
11, nó sẽ không hoạt động. Bạn cũng phải luôn cố gắng xác định
if instance == other_instance:
    #do something
12 trong trường hợp ai đó không có điều kiện sử dụng unicode.
if instance == other_instance:
    #do something
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,
if instance == other_instance:
    #do something
14 sẽ dẫn đến cuộc gọi
if instance == other_instance:
    #do something
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.
if instance == other_instance:
    #do something
16Xác định hành vi khi
if instance == other_instance:
    #do something
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ả
if instance.equals(other_instance):
    # do something
27. Sống theo quy tắc sau.
if instance == other_instance:
    #do something
19 ngụ ý
if instance == other_instance:
    #do something
20.
if instance == other_instance:
    #do something
21Xác định hành vi khi
if instance == other_instance:
    #do something
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ề
if instance == other_instance:
    #do something
23 hoặc
if instance == other_instance:
    #do something
24, tùy thuộc vào việc bạn muốn xem xét trường hợp là
if instance == other_instance:
    #do something
23 hay
if instance == other_instance:
    #do something
24.
if instance == other_instance:
    #do something
27Xác định hành vi khi
if instance == other_instance:
    #do something
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
if instance == other_instance:
    #do something
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
if instance == other_instance:
    #do something
30 hoặc
if instance == other_instance:
    #do something
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.
if instance == other_instance:
    #do something
32Xác định hành vi khi
if instance == other_instance:
    #do something
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

if instance == other_instance:
    #do something
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
if instance == other_instance:
    #do something
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ự.
if instance == other_instance:
    #do something
36Không giống như
if instance == other_instance:
    #do something
30,
if instance == other_instance:
    #do something
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
if instance == other_instance:
    #do something
38, vì ví dụ ở cuối danh sách sẽ hiển thị.
if instance == other_instance:
    #do something
40Điều này hoàn toàn giống với
if instance == other_instance:
    #do something
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
if instance == other_instance:
    #do something
38 để ngăn đệ quy vô hạn (gọi
if instance == other_instance:
    #do something
43 trong quá trình triển khai
if instance == other_instance:
    #do something
44 sẽ gây ra đệ quy vô hạn).
if instance == other_instance:
    #do something
45Sau tất cả những điều này,
if instance == other_instance:
    #do something
31 khá hòa hợp với những người bạn đồng hành của nó là
if instance == other_instance:
    #do something
38 và
if instance == other_instance:
    #do something
44. Tuy nhiên, tôi không khuyên bạn nên sử dụng nó.
if instance == other_instance:
    #do something
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
if instance == other_instance:
    #do something
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
if instance == other_instance:
    #do something
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ề
if instance == other_instance:
    #do something
30, khi
if instance == other_instance:
    #do something
31 được triển khai, chỉ được gọi nếu nó được gọi rõ ràng hoặc một
if instance == other_instance:
    #do something
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

if instance == other_instance:
    #do something
7

Mộ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

if instance == other_instance:
    #do something
55 vì không phải tất cả các lớp đều có thuộc tính
if instance == other_instance:
    #do something
56)

if instance == other_instance:
    #do something
6

Có 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 (

if instance == other_instance:
    #do something
57,
if instance == other_instance:
    #do something
58,
if instance == other_instance:
    #do something
59,
if instance == other_instance:
    #do something
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ầu

Yêu cầu

Bâ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

if instance == other_instance:
    #do something
61 và
if instance == other_instance:
    #do something
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
if instance == other_instance:
    #do something
63 và
if instance == other_instance:
    #do something
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
if instance == other_instance:
    #do something
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à
if instance == other_instance:
    #do something
65(trả về chính nó) và
if instance == other_instance:
    #do something
67

Điều kỳ diệu đằng sau những chiếc container

Còn chần chờ gì nữa, đây là những phương pháp kỳ diệu mà container sử dụng

if instance == other_instance:
    #do something
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.
if instance == other_instance:
    #do something
69Xác định hành vi khi một mục được truy cập, sử dụng ký hiệu
if instance == other_instance:
    #do something
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.
if instance == other_instance:
    #do something
71 nếu loại khóa sai và
if instance == other_instance:
    #do something
72 nếu không có giá trị tương ứng cho khóa.
if instance == other_instance:
    #do something
73Xác định hành vi khi một mục được gán cho, sử dụng ký hiệu
if instance == other_instance:
    #do something
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
if instance == other_instance:
    #do something
72 và
if instance == other_instance:
    #do something
71 khi thích hợp.
if instance == other_instance:
    #do something
77Xác định hành vi khi một mục bị xóa (e. g.
if instance == other_instance:
    #do something
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ệ.
if instance == other_instance:
    #do something
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
if instance == other_instance:
    #do something
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
if instance == other_instance:
    #do something
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
if instance == other_instance:
    #do something
65 trả về
if instance.equals(other_instance):
    # do something
96.
if instance == other_instance:
    #do something
84Được gọi để thực hiện hành vi cho chức năng tích hợp sẵn của
if instance == other_instance:
    #do something
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.
if instance == other_instance:
    #do something
86
if instance == other_instance:
    #do something
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
if instance == other_instance:
    #do something
88 và
if instance == other_instance:
    #do something
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ự? .
if instance == other_instance:
    #do something
92
if instance == other_instance:
    #do something
93 được sử dụng trong các lớp con của
if instance == other_instance:
    #do something
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
if instance == other_instance:
    #do something
95 và nói
if instance == other_instance:
    #do something
96 khi
if instance == other_instance:
    #do something
97 không phải là khóa trong chính tả, thì
if instance == other_instance:
    #do something
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)

if instance == other_instance:
    #do something
6

Bạ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ư

if instance == other_instance:
    #do something
99,
if instance.equals(other_instance):
    # do something
200 và
if instance.equals(other_instance):
    # do something
201

Bạ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

if instance.equals(other_instance):
    # do something
202 và
if instance.equals(other_instance):
    # do something
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à

if instance.equals(other_instance):
    # do something
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.
if instance.equals(other_instance):
    # do something
205.
if instance.equals(other_instance):
    # do something
206Kiểm tra xem một lớp có phân lớp lớp bạn đã xác định không (e. g.
if instance.equals(other_instance):
    # do something
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

if instance.equals(other_instance):
    # do something
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à
if instance.equals(other_instance):
    # do something
209 giống như
if instance.equals(other_instance):
    # do something
210. Lưu ý rằng
if instance.equals(other_instance):
    # do something
211 có số lượng đối số thay đổi;

if instance.equals(other_instance):
    # do something
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

if instance.equals(other_instance):
    # do something
0

Trong 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ố

if instance.equals(other_instance):
    # do something
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
if instance.equals(other_instance):
    # do something
214 trước đây

if instance.equals(other_instance):
    # do something
1

Trì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

if instance.equals(other_instance):
    # do something
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

if instance.equals(other_instance):
    # do something
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
if instance.equals(other_instance):
    # do something
214. Lưu ý rằng giá trị trả về của
if instance.equals(other_instance):
    # do something
219 bị ràng buộc với đích của câu lệnh
if instance.equals(other_instance):
    # do something
214 hoặc tên sau
if instance.equals(other_instance):
    # do something
221.
if instance.equals(other_instance):
    # do something
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,
if instance.equals(other_instance):
    # do something
223,
if instance.equals(other_instance):
    # do something
224 và
if instance.equals(other_instance):
    # do something
225 sẽ là
if instance.equals(other_instance):
    # do something
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

if instance.equals(other_instance):
    # do something
219 và
if instance.equals(other_instance):
    # do something
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ụ

if instance.equals(other_instance):
    # do something
2

Đây là một ví dụ về hoạt động của

if instance.equals(other_instance):
    # do something
231, sử dụng kết nối FTP để chứng minh điều đó (ổ cắm có thể đóng được)

if instance.equals(other_instance):
    # do something
3

Xem 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,

if instance.equals(other_instance):
    # do something
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
if instance.equals(other_instance):
    # do something
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ố

if instance.equals(other_instance):
    # do something
234,
if instance.equals(other_instance):
    # do something
235 và
if instance.equals(other_instance):
    # do something
236 được triển khai. Hãy cùng điểm qua những phương pháp thần kỳ đó nhé

if instance.equals(other_instance):
    # do something
237Xác định hành vi khi giá trị của bộ mô tả được truy xuất.
if instance.equals(other_instance):
    # do something
238 là thể hiện của đối tượng chủ sở hữu.
if instance.equals(other_instance):
    # do something
239 chính là lớp chủ sở hữu.
if instance.equals(other_instance):
    # do something
240Xác định hành vi khi giá trị của bộ mô tả bị thay đổi.
if instance.equals(other_instance):
    # do something
238 là thể hiện của lớp chủ sở hữu và
if instance.equals(other_instance):
    # do something
242 là giá trị để đặt bộ mô tả thành.
if instance.equals(other_instance):
    # do something
243Xác định hành vi khi giá trị của bộ mô tả bị xóa.
if instance.equals(other_instance):
    # do something
238 là thể hiện của đối tượng chủ sở hữu

Bây giờ, một ví dụ về ứng dụng hữu ích của bộ mô tả. chuyển đổi đơn vị

if instance.equals(other_instance):
    # do something
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

if instance.equals(other_instance):
    # do something
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ả

if instance.equals(other_instance):
    # do something
246Xác định hành vi cho
if instance.equals(other_instance):
    # do something
247 đối với các phiên bản của lớp học của bạn.
if instance.equals(other_instance):
    # do something
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).
if instance.equals(other_instance):
    # do something
249Xác định hành vi cho
if instance.equals(other_instance):
    # do something
250 đối với các phiên bản của lớp học của bạn.
if instance.equals(other_instance):
    # do something
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.
if instance.equals(other_instance):
    # do something
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
if instance.equals(other_instance):
    # do something
250 trên thuộc tính đó với
if instance.equals(other_instance):
    # do something
252 làm đối số đầu tiên

Mộ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 (

if instance.equals(other_instance):
    # do something
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ối

Hã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

if instance.equals(other_instance):
    # do something
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ó

if instance.equals(other_instance):
    # do something
5

Bâ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ó

if instance.equals(other_instance):
    # do something
6

Điều gì xảy ra? . Nó giống như chúng ta đã có

if instance.equals(other_instance):
    # do something
257 trong suốt thời gian qua

Bâ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ạn

Pickling 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)

if instance.equals(other_instance):
    # do something
258Nếu bạn muốn
if instance.equals(other_instance):
    # do something
8 được gọi khi lớp của bạn chưa được chọn, bạn có thể định nghĩa
if instance.equals(other_instance):
    # do something
260, nó sẽ trả về một bộ các đối số mà bạn muốn được chuyển đến
if instance.equals(other_instance):
    # do something
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ũ.
if instance.equals(other_instance):
    # do something
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
if instance == other_instance:
    #do something
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
if instance == other_instance:
    #do something
3.
if instance.equals(other_instance):
    # do something
265Thay vì thuộc tính
if instance == other_instance:
    #do something
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
if instance.equals(other_instance):
    # do something
267 khi đối tượng được giải nén.
if instance.equals(other_instance):
    # do something
268Khi đối tượng được giải nén, nếu
if instance.equals(other_instance):
    # do something
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
if instance == other_instance:
    #do something
56 của đối tượng. Điều này đi đôi với
if instance.equals(other_instance):
    # do something
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.
if instance.equals(other_instance):
    # do something
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.
if instance.equals(other_instance):
    # do something
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
if instance.equals(other_instance):
    # do something
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à .
if instance.equals(other_instance):
    # do something
275
if instance.equals(other_instance):
    # do something
276 tồn tại để tương thích. Nếu nó được xác định,
if instance.equals(other_instance):
    # do something
276 sẽ được gọi trên
if instance.equals(other_instance):
    # do something
278 khi ngâm.
if instance.equals(other_instance):
    # do something
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ợ
if instance.equals(other_instance):
    # do something
276

Một ví dụ

Ví dụ của chúng tôi là một

if instance.equals(other_instance):
    # do something
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

if instance.equals(other_instance):
    # do something
7

Mụ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
if instance.equals(other_instance):
    # do something
282
if instance.equals(other_instance):
    # do something
283
if instance == other_instance:
    #do something
3 được gọi khi tạo cá thể
if instance.equals(other_instance):
    # do something
285
if instance.equals(other_instance):
    # do something
283
if instance.equals(other_instance):
    # do something
8 được gọi khi tạo cá thể
if instance.equals(other_instance):
    # do something
28
if instance == other_instance:
    #do something
62,
if instance == other_instance:
    #do something
63, v.v. Called for any comparison
if instance == other_instance:
    #do something
79
if instance.equals(other_instance):
    # do something
292Unary plus sign
if instance == other_instance:
    #do something
61
if instance.equals(other_instance):
    # do something
294Unary minus sign
if instance == other_instance:
    #do something
65
if instance.equals(other_instance):
    # do something
296Bitwise inversion
if instance.equals(other_instance):
    # do something
88
if instance.equals(other_instance):
    # do something
298Conversion when object is used as index
if instance == other_instance:
    #do something
21
if instance.equals(other_instance):
    # do something
200Boolean value of the object
if instance == other_instance:
    #do something
34
if instance.equals(other_instance):
    # do something
202Accessing nonexistent attribute
if instance.equals(other_instance):
    # do something
203
if instance.equals(other_instance):
    # do something
204Assigning to an attribute
if instance == other_instance:
    #do something
40
if instance == other_instance:
    #do something
43Deleting an attribute
if instance == other_instance:
    #do something
45
if instance.equals(other_instance):
    # do something
208Accessing any attribute
if instance == other_instance:
    #do something
69
if instance == other_instance:
    #do something
70Accessing an item using an index
if instance.equals(other_instance):
    # do something
211
if instance.equals(other_instance):
    # do something
212Assigning to an item using an index
if instance == other_instance:
    #do something
77
if instance == other_instance:
    #do something
78Deleting an item using an index
if instance == other_instance:
    #do something
79
if instance.equals(other_instance):
    # do something
216Iteration
if instance.equals(other_instance):
    # do something
217
if instance.equals(other_instance):
    # do something
218,
if instance.equals(other_instance):
    # do something
219Membership tests using
if instance == other_instance:
    #do something
88
if instance.equals(other_instance):
    # do something
221
if instance.equals(other_instance):
    # do something
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