Lập trình hướng đối tượng [OOP] là một phương pháp cấu trúc chương trình bằng cách gộp các thuộc tính và hành vi có liên quan vào các đối tượng riêng lẻ. Trong hướng dẫn này, bạn sẽ tìm hiểu những kiến thức cơ bản về lập trình hướng đối tượng trong Python
Về mặt khái niệm, các đối tượng giống như các thành phần của một hệ thống. Hãy nghĩ về một chương trình như một loại dây chuyền lắp ráp của nhà máy. Tại mỗi bước của dây chuyền lắp ráp, một thành phần hệ thống sẽ xử lý một số vật liệu, cuối cùng biến nguyên liệu thô thành sản phẩm hoàn chỉnh
Một đối tượng chứa dữ liệu, chẳng hạn như nguyên liệu thô hoặc đã được xử lý trước ở mỗi bước trên dây chuyền lắp ráp và hành vi, chẳng hạn như hành động mà mỗi thành phần dây chuyền lắp ráp thực hiện
Trong hướng dẫn này, bạn sẽ học cách
- Tạo một lớp giống như một bản thiết kế để tạo một đối tượng
- Sử dụng các lớp để tạo đối tượng mới
- Hệ thống mô hình với kế thừa lớp
Ghi chú. Hướng dẫn này được chuyển thể từ chương “Lập trình hướng đối tượng [OOP]” trong Python Basics. Giới thiệu thực tế về Python 3
Cuốn sách sử dụng trình soạn thảo IDLE tích hợp sẵn của Python để tạo và chỉnh sửa các tệp Python cũng như tương tác với trình bao Python, do đó, thỉnh thoảng bạn sẽ thấy các tham chiếu đến IDLE trong suốt hướng dẫn này. Tuy nhiên, bạn sẽ không gặp vấn đề gì khi chạy mã ví dụ từ trình chỉnh sửa và môi trường bạn chọn
Tiền thưởng miễn phí. Nhấp vào đây để có quyền truy cập vào Bảng cheat Python OOP miễn phí chỉ cho bạn các hướng dẫn, video và sách hay nhất để tìm hiểu thêm về Lập trình hướng đối tượng với Python
Lập trình hướng đối tượng trong Python là gì?
Lập trình hướng đối tượng là một mô hình lập trình cung cấp phương tiện cấu trúc chương trình sao cho các thuộc tính và hành vi được gộp vào các đối tượng riêng lẻ
Chẳng hạn, một đối tượng có thể đại diện cho một người với các thuộc tính như tên, tuổi, địa chỉ và các hành vi như đi bộ, nói chuyện, thở và chạy. Hoặc nó có thể đại diện cho một email có các thuộc tính như danh sách người nhận, chủ đề và nội dung cũng như các hành vi như thêm tệp đính kèm và gửi
Nói cách khác, lập trình hướng đối tượng là một cách tiếp cận để mô hình hóa các sự vật cụ thể, trong thế giới thực, như ô tô, cũng như mối quan hệ giữa các sự vật, như công ty và nhân viên, học sinh và giáo viên, v.v. OOP mô hình hóa các thực thể trong thế giới thực dưới dạng các đối tượng phần mềm có một số dữ liệu được liên kết với chúng và có thể thực hiện các chức năng nhất định
Một mô hình lập trình phổ biến khác là lập trình thủ tục, cấu trúc một chương trình giống như một công thức trong đó nó cung cấp một tập hợp các bước, dưới dạng các hàm và khối mã, chạy tuần tự để hoàn thành một tác vụ
Điểm mấu chốt là các đối tượng nằm ở trung tâm của lập trình hướng đối tượng trong Python, không chỉ đại diện cho dữ liệu, như trong lập trình thủ tục, mà còn trong cấu trúc tổng thể của chương trình.
Loại bỏ các quảng cáoXác định một lớp trong Python
Các cấu trúc dữ liệu nguyên thủy—như số, chuỗi và danh sách—được thiết kế để biểu diễn các mẩu thông tin đơn giản, chẳng hạn như giá của một quả táo, tên một bài thơ hoặc màu sắc yêu thích của bạn, tương ứng. Nếu bạn muốn đại diện cho một cái gì đó phức tạp hơn thì sao?
Ví dụ: giả sử bạn muốn theo dõi nhân viên trong một tổ chức. Bạn cần lưu trữ một số thông tin cơ bản về từng nhân viên như tên, tuổi, chức vụ, năm bắt đầu làm việc
Một cách để làm điều này là đại diện cho mỗi nhân viên như một danh sách
kirk = ["James Kirk", 34, "Captain", 2265]
spock = ["Spock", 35, "Science Officer", 2254]
mccoy = ["Leonard McCoy", "Chief Medical Officer", 2266]
Có một số vấn đề với cách tiếp cận này
Đầu tiên, nó có thể làm cho các tệp mã lớn khó quản lý hơn. Nếu bạn tham khảo
>>> class Dog:
.. pass
5 cách xa nơi khai báo danh sách >>> class Dog:
.. pass
6 vài dòng, liệu bạn có nhớ rằng phần tử có chỉ số >>> class Dog:
.. pass
7 là tên của nhân viên không?Thứ hai, nó có thể gây ra lỗi nếu không phải mọi nhân viên đều có cùng số phần tử trong danh sách. Trong danh sách
>>> class Dog:
.. pass
8 ở trên, tuổi bị thiếu nên >>> class Dog:
.. pass
9 sẽ trả về >>> Dog[]
0 thay cho Dr. tuổi của McCoyMột cách tuyệt vời để làm cho loại mã này dễ quản lý hơn và dễ bảo trì hơn là sử dụng các lớp
Các lớp so với các trường hợp
Các lớp được sử dụng để tạo cấu trúc dữ liệu do người dùng định nghĩa. Các lớp định nghĩa các hàm được gọi là các phương thức, xác định các hành vi và hành động mà một đối tượng được tạo từ lớp có thể thực hiện với dữ liệu của nó
Trong hướng dẫn này, bạn sẽ tạo một lớp
>>> Dog[]
1 lưu trữ một số thông tin về các đặc điểm và hành vi mà một con chó có thể cóMột lớp là một kế hoạch chi tiết về cách một cái gì đó nên được xác định. Nó không thực sự chứa bất kỳ dữ liệu nào. Lớp
>>> Dog[]
1 chỉ định rằng tên và tuổi là cần thiết để xác định một con chó, nhưng nó không chứa tên hoặc tuổi của bất kỳ con chó cụ thể nàoTrong khi lớp là bản thiết kế, thì một thể hiện là một đối tượng được xây dựng từ một lớp và chứa dữ liệu thực. Một thể hiện của lớp
>>> Dog[]
1 không còn là bản thiết kế nữa. Đó là một con chó thực sự có tên, như Miles, bốn tuổiNói cách khác, một lớp giống như một biểu mẫu hoặc bảng câu hỏi. Một ví dụ giống như một biểu mẫu đã được điền thông tin. Giống như nhiều người có thể điền vào cùng một biểu mẫu với thông tin duy nhất của riêng họ, nhiều trường hợp có thể được tạo từ một lớp duy nhất
Cách xác định một lớp
Tất cả các định nghĩa lớp bắt đầu bằng từ khóa
>>> Dog[]
4, theo sau là tên của lớp và dấu hai chấm. Bất kỳ mã nào được thụt vào bên dưới định nghĩa lớp được coi là một phần của nội dung lớpĐây là một ví dụ về một lớp học
>>> Dog[]
1class Dog:
pass
Phần thân của lớp
>>> Dog[]
1 bao gồm một câu lệnh đơn. từ khóa >>> Dog[]
7. >>> Dog[]
7 thường được sử dụng làm trình giữ chỗ cho biết mã cuối cùng sẽ đi đến đâu. Nó cho phép bạn chạy mã này mà Python không báo lỗiGhi chú. Tên lớp Python được viết bằng ký hiệu CapitalizedWords theo quy ước. Ví dụ: một lớp dành cho một giống chó cụ thể như Jack Russell Terrier sẽ được viết là
>>> Dog[]
9Lớp
>>> Dog[]
1 hiện không thú vị lắm, vì vậy hãy cải thiện nó một chút bằng cách xác định một số thuộc tính mà tất cả các đối tượng >>> Dog[]
1 nên có. Có một số thuộc tính mà chúng ta có thể chọn, bao gồm tên, tuổi, màu lông và giống. Để giữ cho mọi thứ đơn giản, chúng tôi sẽ chỉ sử dụng tên và tuổiCác thuộc tính mà tất cả các đối tượng
>>> Dog[]
1 phải có được định nghĩa trong một phương thức có tên là >>> Dog[]
3. Mỗi khi một đối tượng >>> Dog[]
1 mới được tạo, >>> Dog[]
3 sẽ đặt trạng thái ban đầu của đối tượng bằng cách gán các giá trị thuộc tính của đối tượng. Tức là, >>> Dog[]
3 khởi tạo từng phiên bản mới của lớpBạn có thể cung cấp cho
>>> Dog[]
3 bất kỳ số lượng tham số nào, nhưng tham số đầu tiên sẽ luôn là một biến có tên là >>> Dog[]
8. Khi một thể hiện lớp mới được tạo, thể hiện đó sẽ tự động được chuyển đến tham số >>> Dog[]
8 trong >>> Dog[]
3 để có thể xác định các thuộc tính mới trên đối tượngHãy cập nhật lớp
>>> Dog[]
1 với một phương thức >>> Dog[]
3 để tạo các thuộc tính >>> a = Dog[]
>>> b = Dog[]
>>> a == b
False
3 và >>> a = Dog[]
>>> b = Dog[]
>>> a == b
False
4class Dog:
def __init__[self, name, age]:
self.name = name
self.age = age
Lưu ý rằng chữ ký của phương thức
>>> Dog[]
3 được thụt vào bốn khoảng trắng. Phần thân của phương thức được thụt vào bởi tám khoảng trắng. Dấu đầu dòng này cực kỳ quan trọng. Nó nói với Python rằng phương thức >>> Dog[]
3 thuộc về lớp >>> Dog[]
1Trong phần thân của
>>> Dog[]
3, có hai câu lệnh sử dụng biến >>> Dog[]
8
0 tạo một thuộc tính có tên là>>> class Dog: .. species = "Canis familiaris" .. def __init__[self, name, age]: .. self.name = name .. self.age = age
1 và gán cho nó giá trị của tham số>>> class Dog: .. species = "Canis familiaris" .. def __init__[self, name, age]: .. self.name = name .. self.age = age
1>>> class Dog: .. species = "Canis familiaris" .. def __init__[self, name, age]: .. self.name = name .. self.age = age
3 tạo một thuộc tính có tên là>>> class Dog: .. species = "Canis familiaris" .. def __init__[self, name, age]: .. self.name = name .. self.age = age
4 và gán cho nó giá trị của tham số>>> class Dog: .. species = "Canis familiaris" .. def __init__[self, name, age]: .. self.name = name .. self.age = age
4>>> class Dog: .. species = "Canis familiaris" .. def __init__[self, name, age]: .. self.name = name .. self.age = age
Thuộc tính được tạo trong
>>> Dog[]
3 được gọi là thuộc tính thể hiện. Giá trị của một thuộc tính thể hiện là dành riêng cho một thể hiện cụ thể của lớp. Tất cả các đối tượng >>> Dog[]
1 đều có tên và tuổi, nhưng các giá trị cho các thuộc tính >>> class Dog:
.. species = "Canis familiaris"
.. def __init__[self, name, age]:
.. self.name = name
.. self.age = age
1 và >>> class Dog:
.. species = "Canis familiaris"
.. def __init__[self, name, age]:
.. self.name = name
.. self.age = age
4 sẽ khác nhau tùy thuộc vào trường hợp >>> Dog[]
1Mặt khác, thuộc tính lớp là thuộc tính có cùng giá trị cho tất cả các thể hiện của lớp. Bạn có thể xác định thuộc tính lớp bằng cách gán giá trị cho tên biến bên ngoài
>>> Dog[]
3Ví dụ: lớp
>>> Dog[]
1 sau đây có thuộc tính lớp được gọi là >>> Dog[]
Traceback [most recent call last]:
File "", line 1, in
Dog[]
TypeError: __init__[] missing 2 required positional arguments: 'name' and 'age'
3 với giá trị >>> Dog[]
Traceback [most recent call last]:
File "", line 1, in
Dog[]
TypeError: __init__[] missing 2 required positional arguments: 'name' and 'age'
4class Dog:
# Class attribute
species = "Canis familiaris"
def __init__[self, name, age]:
self.name = name
self.age = age
Các thuộc tính của lớp được xác định trực tiếp bên dưới dòng đầu tiên của tên lớp và được thụt vào bởi bốn khoảng trắng. Chúng phải luôn được gán một giá trị ban đầu. Khi một thể hiện của lớp được tạo, các thuộc tính của lớp sẽ tự động được tạo và gán cho các giá trị ban đầu của chúng
Sử dụng các thuộc tính của lớp để xác định các thuộc tính phải có cùng giá trị cho mọi thể hiện của lớp. Sử dụng thuộc tính phiên bản cho các thuộc tính thay đổi từ phiên bản này sang phiên bản khác
Bây giờ chúng ta có một lớp
>>> Dog[]
1, hãy tạo một số con chóLoại bỏ các quảng cáoKhởi tạo một đối tượng trong Python
Mở cửa sổ tương tác của IDLE và gõ như sau
>>>
>>> class Dog:
.. pass
Điều này tạo ra một lớp
>>> Dog[]
1 mới không có thuộc tính hoặc phương thứcTạo một đối tượng mới từ một lớp được gọi là khởi tạo một đối tượng. Bạn có thể khởi tạo một đối tượng
>>> Dog[]
1 mới bằng cách nhập tên của lớp, tiếp theo là mở và đóng dấu ngoặc đơn>>>
>>> Dog[]
Bây giờ bạn có một đối tượng
>>> Dog[]
1 mới tại >>> Dog[]
Traceback [most recent call last]:
File "", line 1, in
Dog[]
TypeError: __init__[] missing 2 required positional arguments: 'name' and 'age'
9. Chuỗi ký tự và số trông buồn cười này là một địa chỉ bộ nhớ cho biết nơi lưu trữ đối tượng >>> Dog[]
1 trong bộ nhớ máy tính của bạn. Lưu ý rằng địa chỉ bạn nhìn thấy trên màn hình sẽ khácBây giờ khởi tạo một đối tượng
>>> Dog[]
1 thứ hai>>>
>>> Dog[]
Phiên bản
>>> Dog[]
1 mới được đặt tại một địa chỉ bộ nhớ khác. Đó là bởi vì nó là một thể hiện hoàn toàn mới và hoàn toàn độc nhất so với đối tượng >>> Dog[]
1 đầu tiên mà bạn đã khởi tạoĐể xem điều này theo cách khác, hãy gõ như sau
>>>
>>> a = Dog[]
>>> b = Dog[]
>>> a == b
False
Trong mã này, bạn tạo hai đối tượng
>>> Dog[]
1 mới và gán chúng cho các biến class Dog:
pass
05 và class Dog:
pass
06. Khi bạn so sánh class Dog:
pass
05 và class Dog:
pass
06 sử dụng toán tử class Dog:
pass
09, kết quả là class Dog:
pass
10. Mặc dù class Dog:
pass
05 và class Dog:
pass
06 đều là thể hiện của lớp >>> Dog[]
1, nhưng chúng đại diện cho hai đối tượng riêng biệt trong bộ nhớThuộc tính lớp và trường hợp
Bây giờ hãy tạo một lớp
>>> Dog[]
1 mới với thuộc tính lớp có tên là class Dog:
pass
15 và hai thuộc tính thể hiện có tên là >>> a = Dog[]
>>> b = Dog[]
>>> a == b
False
3 và >>> a = Dog[]
>>> b = Dog[]
>>> a == b
False
4>>>
>>> class Dog:
.. species = "Canis familiaris"
.. def __init__[self, name, age]:
.. self.name = name
.. self.age = age
Để khởi tạo các đối tượng của lớp
>>> Dog[]
1 này, bạn cần cung cấp các giá trị cho >>> class Dog:
.. species = "Canis familiaris"
.. def __init__[self, name, age]:
.. self.name = name
.. self.age = age
1 và >>> class Dog:
.. species = "Canis familiaris"
.. def __init__[self, name, age]:
.. self.name = name
.. self.age = age
4. Nếu bạn không làm như vậy, thì Python sẽ tăng class Dog:
pass
21>>>
>>> Dog[]
Traceback [most recent call last]:
File "", line 1, in
Dog[]
TypeError: __init__[] missing 2 required positional arguments: 'name' and 'age'
Để truyền đối số cho tham số
>>> class Dog:
.. species = "Canis familiaris"
.. def __init__[self, name, age]:
.. self.name = name
.. self.age = age
1 và >>> class Dog:
.. species = "Canis familiaris"
.. def __init__[self, name, age]:
.. self.name = name
.. self.age = age
4, hãy đặt giá trị vào dấu ngoặc đơn sau tên lớp>>>
class Dog:
pass
0Điều này tạo ra hai phiên bản
>>> Dog[]
1 mới—một dành cho chú chó chín tuổi tên Buddy và một dành cho chú chó bốn tuổi tên MilesPhương thức
>>> Dog[]
3 của lớp >>> Dog[]
1 có ba tham số, vậy tại sao chỉ có hai đối số được truyền cho nó trong ví dụ?Khi bạn khởi tạo một đối tượng
>>> Dog[]
1, Python sẽ tạo một thể hiện mới và chuyển nó tới tham số đầu tiên của >>> Dog[]
3. Điều này về cơ bản sẽ loại bỏ tham số >>> Dog[]
8, vì vậy bạn chỉ cần lo lắng về các tham số >>> class Dog:
.. species = "Canis familiaris"
.. def __init__[self, name, age]:
.. self.name = name
.. self.age = age
1 và >>> class Dog:
.. species = "Canis familiaris"
.. def __init__[self, name, age]:
.. self.name = name
.. self.age = age
4Sau khi bạn tạo phiên bản
>>> Dog[]
1, bạn có thể truy cập các thuộc tính phiên bản của chúng bằng cách sử dụng ký hiệu dấu chấm>>>
class Dog:
pass
1Bạn có thể truy cập các thuộc tính của lớp theo cùng một cách
>>>
class Dog:
pass
2Một trong những lợi thế lớn nhất của việc sử dụng các lớp để tổ chức dữ liệu là các phiên bản được đảm bảo có các thuộc tính mà bạn mong đợi. Tất cả các phiên bản
>>> Dog[]
1 đều có các thuộc tính class Dog:
pass
15, >>> a = Dog[]
>>> b = Dog[]
>>> a == b
False
3 và >>> a = Dog[]
>>> b = Dog[]
>>> a == b
False
4, vì vậy bạn có thể yên tâm sử dụng các thuộc tính đó khi biết rằng chúng sẽ luôn trả về một giá trịMặc dù các thuộc tính được đảm bảo tồn tại nhưng giá trị của chúng có thể thay đổi linh hoạt
>>>
class Dog:
pass
3Trong ví dụ này, bạn thay đổi thuộc tính
>>> a = Dog[]
>>> b = Dog[]
>>> a == b
False
4 của đối tượng class Dog:
pass
38 thành class Dog:
pass
39. Sau đó, bạn thay đổi thuộc tính class Dog:
pass
15 của đối tượng class Dog:
pass
41 thành class Dog:
pass
42, đó là một loài mèo. Điều đó khiến Miles trở thành một con chó khá kỳ lạ, nhưng nó hợp lệ PythonĐiểm mấu chốt ở đây là các đối tượng tùy chỉnh có thể thay đổi theo mặc định. Một đối tượng có thể thay đổi nếu nó có thể thay đổi động. Ví dụ: danh sách và từ điển có thể thay đổi nhưng chuỗi và bộ dữ liệu là bất biến
Loại bỏ các quảng cáoPhương thức sơ thẩm
Các phương thức sơ thẩm là các hàm được định nghĩa bên trong một lớp và chỉ có thể được gọi từ một thể hiện của lớp đó. Giống như
>>> Dog[]
3, tham số đầu tiên của phương thức thể hiện luôn là >>> Dog[]
8Mở một cửa sổ soạn thảo mới trong IDLE và nhập vào lớp
>>> Dog[]
1 sauclass Dog:
pass
4Lớp
>>> Dog[]
1 này có hai phương thức thể hiện
47 trả về một chuỗi hiển thị tên và tuổi của con chóclass Dog: pass
48 có một tham số được gọi làclass Dog: pass
49 và trả về một chuỗi chứa tên của con chó và âm thanh mà con chó tạo raclass Dog: pass
Lưu lớp
>>> Dog[]
1 đã sửa đổi vào tệp có tên class Dog:
pass
51 và nhấn F5 để chạy chương trình. Sau đó, mở cửa sổ tương tác và nhập nội dung sau để xem các phương thức phiên bản của bạn đang hoạt động. >>>
class Dog:
pass
5Trong lớp
>>> Dog[]
1 ở trên, class Dog:
pass
47 trả về một chuỗi chứa thông tin về trường hợp >>> Dog[]
1 class Dog:
pass
41. Khi viết các lớp của riêng bạn, bạn nên có một phương thức trả về một chuỗi chứa thông tin hữu ích về một thể hiện của lớp. Tuy nhiên, class Dog:
pass
47 không phải là cách Pythonic nhất để làm điều nàyKhi bạn tạo một đối tượng
class Dog:
pass
57, bạn có thể sử dụng class Dog:
pass
58 để hiển thị một chuỗi giống như danh sách>>>
class Dog:
pass
6Hãy xem điều gì sẽ xảy ra khi bạn
class Dog:
pass
58 đối tượng class Dog:
pass
41>>>
class Dog:
pass
7Khi bạn
class Dog:
pass
61, bạn nhận được một thông báo có vẻ khó hiểu cho bạn biết rằng class Dog:
pass
41 là một đối tượng >>> Dog[]
1 tại địa chỉ bộ nhớ class Dog:
pass
64. Thông báo này không hữu ích lắm. Bạn có thể thay đổi nội dung được in bằng cách xác định một phương thức thể hiện đặc biệt có tên là class Dog:
pass
65Trong cửa sổ soạn thảo, thay đổi tên của phương thức
class Dog:
pass
47 của lớp >>> Dog[]
1 thành class Dog:
pass
65class Dog:
pass
8Lưu tệp và nhấn F5 . Bây giờ, khi bạn
class Dog:
pass
61, bạn sẽ nhận được kết quả thân thiện hơn nhiều. >>>
class Dog:
pass
9Các phương thức như
>>> Dog[]
3 và class Dog:
pass
65 được gọi là phương thức dunder vì chúng bắt đầu và kết thúc bằng hai dấu gạch dưới. Có nhiều phương thức khác mà bạn có thể sử dụng để tùy chỉnh các lớp trong Python. Mặc dù một chủ đề quá nâng cao đối với một cuốn sách Python mới bắt đầu, nhưng việc hiểu các phương thức dunder là một phần quan trọng để thành thạo lập trình hướng đối tượng trong PythonTrong phần tiếp theo, bạn sẽ thấy cách nâng cao kiến thức của mình thêm một bước nữa và tạo các lớp từ các lớp khác
Loại bỏ các quảng cáoKiểm tra việc hiểu của bạn
Mở rộng khối bên dưới để kiểm tra sự hiểu biết của bạn
Tập thể dục. Tạo một loại ô tôHiển thị/Ẩn
Tạo một lớp
class Dog:
pass
72 với hai thuộc tính thể hiện
73, lưu tên màu của ô tô dưới dạng một chuỗiclass Dog: pass
74, lưu trữ số dặm trên xe dưới dạng số nguyênclass Dog: pass
Sau đó, khởi tạo hai đối tượng
class Dog:
pass
72—một ô tô màu xanh với 20.000 dặm và một ô tô màu đỏ với 30.000 dặm—và in ra màu sắc và số dặm của chúng. Đầu ra của bạn sẽ trông như thế nàyclass Dog:
def __init__[self, name, age]:
self.name = name
self.age = age
0Bạn có thể mở rộng khối bên dưới để xem giải pháp
Giải pháp. Tạo một loại ô tôHiển thị/Ẩn
Đầu tiên, tạo một lớp
class Dog:
pass
72 với các thuộc tính thực thể class Dog:
pass
73 và class Dog:
pass
74class Dog:
def __init__[self, name, age]:
self.name = name
self.age = age
1Các tham số
class Dog:
pass
79 và class Dog:
pass
80 của >>> Dog[]
3 được gán cho class Dog:
pass
82 và class Dog:
pass
83, tạo ra hai thuộc tính thể hiệnBây giờ bạn có thể tạo hai phiên bản
class Dog:
pass
72class Dog:
def __init__[self, name, age]:
self.name = name
self.age = age
2Phiên bản
class Dog:
pass
85 được tạo bằng cách chuyển giá trị class Dog:
pass
86 cho tham số class Dog:
pass
79 và class Dog:
pass
88 cho tham số class Dog:
pass
80. Tương tự, class Dog:
pass
90 được tạo với các giá trị class Dog:
pass
91 và class Dog:
pass
92Để in màu và số dặm của từng đối tượng
class Dog:
pass
72, bạn có thể lặp lại một class Dog:
pass
94 chứa cả hai đối tượngclass Dog:
def __init__[self, name, age]:
self.name = name
self.age = age
3Chuỗi f trong vòng lặp
class Dog:
pass
95 ở trên chèn các thuộc tính class Dog:
pass
73 và class Dog:
pass
74 vào chuỗi và sử dụng class Dog:
pass
98 để in số dặm được nhóm theo hàng nghìn và được phân tách bằng dấu phẩyĐầu ra cuối cùng trông như thế này
class Dog:
def __init__[self, name, age]:
self.name = name
self.age = age
0Khi bạn đã sẵn sàng, bạn có thể chuyển sang phần tiếp theo
Kế thừa từ các lớp khác trong Python
Kế thừa là quá trình mà một lớp đảm nhận các thuộc tính và phương thức của lớp khác. Các lớp mới được tạo thành được gọi là lớp con và các lớp mà các lớp con được dẫn xuất từ đó được gọi là lớp cha
Ghi chú. Hướng dẫn này được chuyển thể từ chương “Lập trình hướng đối tượng [OOP]” trong Python Basics. Giới thiệu thực tế về Python 3. Nếu bạn thích những gì bạn đang đọc, thì hãy nhớ xem phần còn lại của cuốn sách
Các lớp con có thể ghi đè hoặc mở rộng các thuộc tính và phương thức của các lớp cha. Nói cách khác, các lớp con kế thừa tất cả các thuộc tính và phương thức của lớp cha nhưng cũng có thể chỉ định các thuộc tính và phương thức duy nhất cho chính chúng
Mặc dù phép loại suy không hoàn hảo, nhưng bạn có thể nghĩ về kiểu thừa kế đối tượng giống như kiểu thừa kế di truyền
Bạn có thể đã thừa hưởng màu tóc từ mẹ của bạn. Đó là một thuộc tính mà bạn được sinh ra với. Giả sử bạn quyết định nhuộm tóc màu tím. Giả sử mẹ bạn không có tóc màu tím, bạn vừa ghi đè thuộc tính màu tóc mà bạn được thừa hưởng từ mẹ mình
Theo một nghĩa nào đó, bạn cũng được thừa hưởng ngôn ngữ của mình từ cha mẹ. Nếu cha mẹ bạn nói tiếng Anh, thì bạn cũng sẽ nói tiếng Anh. Bây giờ hãy tưởng tượng bạn quyết định học một ngôn ngữ thứ hai, chẳng hạn như tiếng Đức. Trong trường hợp này, bạn đã mở rộng các thuộc tính của mình vì bạn đã thêm một thuộc tính mà cha mẹ bạn không có
Ví dụ về công viên chó
Giả vờ trong giây lát rằng bạn đang ở công viên dành cho chó. Có rất nhiều giống chó khác nhau tại công viên, tất cả đều tham gia vào các hành vi khác nhau của chó
Giả sử bây giờ bạn muốn lập mô hình công viên dành cho chó với các lớp Python. Lớp
>>> Dog[]
1 mà bạn đã viết trong phần trước có thể phân biệt chó theo tên và tuổi nhưng không phải theo giốngBạn có thể sửa đổi lớp
>>> Dog[]
1 trong cửa sổ soạn thảo bằng cách thêm thuộc tính class Dog:
def __init__[self, name, age]:
self.name = name
self.age = age
01class Dog:
def __init__[self, name, age]:
self.name = name
self.age = age
5Các phương thức thể hiện được xác định trước đó được bỏ qua ở đây vì chúng không quan trọng đối với cuộc thảo luận này
Nhấn F5 để lưu tệp. Giờ đây, bạn có thể lập mô hình công viên dành cho chó bằng cách khởi tạo một loạt các chú chó khác nhau trong cửa sổ tương tác.
>>>
class Dog:
def __init__[self, name, age]:
self.name = name
self.age = age
6Mỗi giống chó có hành vi hơi khác nhau. Ví dụ, chó bulgie có tiếng sủa trầm nghe giống như tiếng gâu gâu, nhưng chó dachshund có tiếng sủa cao hơn nghe giống tiếng yap hơn
Chỉ sử dụng lớp
>>> Dog[]
1, bạn phải cung cấp một chuỗi cho đối số class Dog:
pass
49 của class Dog:
pass
48 mỗi khi bạn gọi nó trong trường hợp >>> Dog[]
1>>>
class Dog:
def __init__[self, name, age]:
self.name = name
self.age = age
7Việc chuyển một chuỗi cho mọi cuộc gọi đến ____12_______48 lặp đi lặp lại và bất tiện. Ngoài ra, chuỗi đại diện cho âm thanh mà mỗi phiên bản
>>> Dog[]
1 tạo ra phải được xác định bởi thuộc tính class Dog:
def __init__[self, name, age]:
self.name = name
self.age = age
01 của nó, nhưng ở đây bạn phải chuyển chuỗi chính xác theo cách thủ công cho class Dog:
pass
48 mỗi khi nó được gọiBạn có thể đơn giản hóa trải nghiệm làm việc với lớp
>>> Dog[]
1 bằng cách tạo một lớp con cho mỗi giống chó. Điều này cho phép bạn mở rộng chức năng mà mỗi lớp con kế thừa, bao gồm chỉ định đối số mặc định cho class Dog:
pass
48Loại bỏ các quảng cáoLớp cha mẹ so với lớp con
Hãy tạo một lớp con cho mỗi trong ba giống được đề cập ở trên. Jack Russell Terrier, Dachshund và Bulldog
Để tham khảo, đây là định nghĩa đầy đủ của lớp
>>> Dog[]
1class Dog:
def __init__[self, name, age]:
self.name = name
self.age = age
8Hãy nhớ rằng, để tạo một lớp con, bạn tạo lớp mới với tên riêng của nó và sau đó đặt tên của lớp cha trong ngoặc đơn. Thêm phần sau vào tệp
class Dog:
pass
51 để tạo ba lớp con mới của lớp >>> Dog[]
1class Dog:
def __init__[self, name, age]:
self.name = name
self.age = age
9Nhấn F5 để lưu và chạy tệp. Với các lớp con đã được xác định, giờ đây bạn có thể khởi tạo một số giống chó cụ thể trong cửa sổ tương tác.
>>>
class Dog:
# Class attribute
species = "Canis familiaris"
def __init__[self, name, age]:
self.name = name
self.age = age
0Các thể hiện của lớp con kế thừa tất cả các thuộc tính và phương thức của lớp cha
>>>
class Dog:
# Class attribute
species = "Canis familiaris"
def __init__[self, name, age]:
self.name = name
self.age = age
1Để xác định đối tượng đã cho thuộc về lớp nào, bạn có thể sử dụng hàm tích hợp sẵn
class Dog:
def __init__[self, name, age]:
self.name = name
self.age = age
15>>>
class Dog:
# Class attribute
species = "Canis familiaris"
def __init__[self, name, age]:
self.name = name
self.age = age
2Điều gì sẽ xảy ra nếu bạn muốn xác định xem
class Dog:
pass
41 có phải là một thể hiện của lớp >>> Dog[]
1 hay không? >>>
class Dog:
# Class attribute
species = "Canis familiaris"
def __init__[self, name, age]:
self.name = name
self.age = age
3Lưu ý rằng
class Dog:
def __init__[self, name, age]:
self.name = name
self.age = age
18 có hai đối số, một đối tượng và một lớp. Trong ví dụ trên, class Dog:
def __init__[self, name, age]:
self.name = name
self.age = age
18 kiểm tra xem class Dog:
pass
41 có phải là một thể hiện của lớp >>> Dog[]
1 hay không và trả về class Dog:
def __init__[self, name, age]:
self.name = name
self.age = age
23Các đối tượng
class Dog:
pass
41, class Dog:
pass
38, class Dog:
def __init__[self, name, age]:
self.name = name
self.age = age
26 và class Dog:
def __init__[self, name, age]:
self.name = name
self.age = age
27 đều là phiên bản >>> Dog[]
1, nhưng class Dog:
pass
41 không phải là phiên bản class Dog:
def __init__[self, name, age]:
self.name = name
self.age = age
30 và class Dog:
def __init__[self, name, age]:
self.name = name
self.age = age
26 không phải là phiên bản class Dog:
def __init__[self, name, age]:
self.name = name
self.age = age
32>>>
class Dog:
# Class attribute
species = "Canis familiaris"
def __init__[self, name, age]:
self.name = name
self.age = age
4Tổng quát hơn, tất cả các đối tượng được tạo từ một lớp con là thể hiện của lớp cha, mặc dù chúng có thể không phải là thể hiện của các lớp con khác
Bây giờ bạn đã tạo các lớp con cho một số giống chó khác nhau, hãy cung cấp cho mỗi giống chó âm thanh riêng
Mở rộng chức năng của lớp cha
Vì các giống chó khác nhau có tiếng sủa hơi khác nhau, nên bạn muốn cung cấp giá trị mặc định cho đối số
class Dog:
pass
49 của các phương thức class Dog:
pass
48 tương ứng của chúng. Để thực hiện việc này, bạn cần ghi đè lên class Dog:
pass
48 trong định nghĩa lớp cho từng giốngĐể ghi đè một phương thức được định nghĩa trên lớp cha, bạn định nghĩa một phương thức có cùng tên trên lớp con. Đây là giao diện của lớp
>>> Dog[]
9class Dog:
# Class attribute
species = "Canis familiaris"
def __init__[self, name, age]:
self.name = name
self.age = age
5Bây giờ
class Dog:
pass
48 được định nghĩa trên lớp >>> Dog[]
9 với đối số mặc định cho class Dog:
pass
49 được đặt thành class Dog:
def __init__[self, name, age]:
self.name = name
self.age = age
40Cập nhật
class Dog:
pass
51 với lớp >>> Dog[]
9 mới và nhấn F5 để lưu và chạy tệp. Bây giờ, bạn có thể gọi class Dog:
pass
48 trong trường hợp >>> Dog[]
9 mà không cần chuyển đối số tới class Dog:
pass
49. >>>
class Dog:
# Class attribute
species = "Canis familiaris"
def __init__[self, name, age]:
self.name = name
self.age = age
6Đôi khi chó tạo ra những tiếng sủa khác nhau, vì vậy nếu Miles tức giận và gầm gừ, bạn vẫn có thể gọi
class Dog:
pass
48 bằng một âm thanh khác>>>
class Dog:
# Class attribute
species = "Canis familiaris"
def __init__[self, name, age]:
self.name = name
self.age = age
7Một điều cần lưu ý về kế thừa lớp là các thay đổi đối với lớp cha sẽ tự động lan truyền sang các lớp con. Điều này xảy ra miễn là thuộc tính hoặc phương thức được thay đổi không bị ghi đè trong lớp con
Ví dụ: trong cửa sổ soạn thảo, thay đổi chuỗi được trả về bởi
class Dog:
pass
48 trong lớp >>> Dog[]
1class Dog:
# Class attribute
species = "Canis familiaris"
def __init__[self, name, age]:
self.name = name
self.age = age
8Lưu tệp và nhấn F5 . Bây giờ, khi bạn tạo một phiên bản
class Dog:
def __init__[self, name, age]:
self.name = name
self.age = age
30 mới có tên là class Dog:
def __init__[self, name, age]:
self.name = name
self.age = age
27, thì class Dog:
def __init__[self, name, age]:
self.name = name
self.age = age
51 trả về chuỗi mới. >>>
class Dog:
# Class attribute
species = "Canis familiaris"
def __init__[self, name, age]:
self.name = name
self.age = age
9Tuy nhiên, gọi
class Dog:
pass
48 trên phiên bản >>> Dog[]
9 sẽ không hiển thị kiểu đầu ra mới>>>
class Dog:
# Class attribute
species = "Canis familiaris"
def __init__[self, name, age]:
self.name = name
self.age = age
6Đôi khi, thật hợp lý khi ghi đè hoàn toàn một phương thức từ lớp cha. Nhưng trong trường hợp này, chúng tôi không muốn lớp
>>> Dog[]
9 mất bất kỳ thay đổi nào có thể được thực hiện đối với định dạng của chuỗi đầu ra của class Dog:
def __init__[self, name, age]:
self.name = name
self.age = age
55Để làm điều này, bạn vẫn cần định nghĩa một phương thức
class Dog:
pass
48 trên lớp con >>> Dog[]
9. Nhưng thay vì xác định rõ ràng chuỗi đầu ra, bạn cần gọi lớp >>> Dog[]
1 của lớp class Dog:
pass
48 bên trong lớp con của lớp class Dog:
pass
48 bằng cách sử dụng cùng các đối số mà bạn đã truyền cho class Dog:
def __init__[self, name, age]:
self.name = name
self.age = age
61Bạn có thể truy cập lớp cha từ bên trong một phương thức của lớp con bằng cách sử dụng
class Dog:
def __init__[self, name, age]:
self.name = name
self.age = age
62>>> class Dog:
.. pass
1Khi bạn gọi
class Dog:
def __init__[self, name, age]:
self.name = name
self.age = age
63 bên trong >>> Dog[]
9, Python sẽ tìm kiếm lớp cha, >>> Dog[]
1, để tìm một phương thức class Dog:
pass
48 và gọi nó với biến class Dog:
pass
49Cập nhật
class Dog:
pass
51 với lớp >>> Dog[]
9 mới. Lưu tệp và nhấn F5 để bạn có thể kiểm tra tệp trong cửa sổ tương tác. >>>
>>> class Dog:
.. pass
2Bây giờ khi bạn gọi
class Dog:
def __init__[self, name, age]:
self.name = name
self.age = age
70, bạn sẽ thấy đầu ra phản ánh định dạng mới trong lớp >>> Dog[]
1Ghi chú. Trong các ví dụ trên, hệ thống phân cấp lớp rất đơn giản. Lớp
>>> Dog[]
9 có một lớp cha duy nhất, >>> Dog[]
1. Trong các ví dụ thực tế, hệ thống phân cấp lớp có thể trở nên khá phức tạpclass Dog:
def __init__[self, name, age]:
self.name = name
self.age = age
62 làm được nhiều việc hơn là chỉ tìm kiếm phương thức hoặc thuộc tính trong lớp cha. Nó đi qua toàn bộ hệ thống phân cấp lớp cho một phương thức hoặc thuộc tính phù hợp. Nếu bạn không cẩn thận, class Dog:
def __init__[self, name, age]:
self.name = name
self.age = age
62 có thể gây ra kết quả đáng ngạc nhiênLoại bỏ các quảng cáoKiểm tra việc hiểu của bạn
Mở rộng khối bên dưới để kiểm tra sự hiểu biết của bạn
Tập thể dục. Kế thừa lớpHiển thị/Ẩn
Tạo một lớp
class Dog:
def __init__[self, name, age]:
self.name = name
self.age = age
76 kế thừa từ lớp >>> Dog[]
1. Cung cấp cho đối số class Dog:
pass
49 của class Dog:
def __init__[self, name, age]:
self.name = name
self.age = age
79 một giá trị mặc định là class Dog:
def __init__[self, name, age]:
self.name = name
self.age = age
80. Sử dụng đoạn mã sau cho lớp học >>> Dog[]
1 phụ huynh của bạnclass Dog:
def __init__[self, name, age]:
self.name = name
self.age = age
8Bạn có thể mở rộng khối bên dưới để xem giải pháp
Giải pháp. Kế thừa lớpHiển thị/Ẩn
Tạo một lớp có tên là
class Dog:
def __init__[self, name, age]:
self.name = name
self.age = age
76 kế thừa từ lớp >>> Dog[]
1 và ghi đè phương thức class Dog:
pass
48>>> class Dog:
.. pass
4Tham số
class Dog:
pass
49 trong class Dog:
def __init__[self, name, age]:
self.name = name
self.age = age
79 được cung cấp giá trị mặc định là class Dog:
def __init__[self, name, age]:
self.name = name
self.age = age
80. Sau đó, class Dog:
def __init__[self, name, age]:
self.name = name
self.age = age
62 được sử dụng để gọi phương thức class Dog:
pass
48 của lớp cha với cùng một đối số được truyền cho class Dog:
pass
49 như phương thức class Dog:
pass
48 của lớp class Dog:
def __init__[self, name, age]:
self.name = name
self.age = age
76Phần kết luận
Trong hướng dẫn này, bạn đã học về lập trình hướng đối tượng [OOP] trong Python. Hầu hết các ngôn ngữ lập trình hiện đại, chẳng hạn như Java, C# và C++, đều tuân theo các nguyên tắc OOP, vì vậy kiến thức bạn thu được ở đây sẽ được áp dụng cho dù sự nghiệp lập trình của bạn đưa bạn đến đâu.
Trong hướng dẫn này, bạn đã học cách
- Định nghĩa một lớp, là một loại bản thiết kế cho một đối tượng
- Khởi tạo một đối tượng từ một lớp
- Sử dụng các thuộc tính và phương thức để xác định các thuộc tính và hành vi của một đối tượng
- Sử dụng tính kế thừa để tạo các lớp con từ lớp cha
- Tham chiếu một phương thức trên lớp cha bằng cách sử dụng
62class Dog: def __init__[self, name, age]: self.name = name self.age = age
- Kiểm tra xem một đối tượng có kế thừa từ một lớp khác hay không bằng cách sử dụng
18class Dog: def __init__[self, name, age]: self.name = name self.age = age
Nếu bạn thích những gì bạn học được trong ví dụ này từ Python Basics. Giới thiệu thực tế về Python 3, thì hãy nhớ xem phần còn lại của cuốn sách
Đánh dấu là đã hoàn thành
Xem ngay Hướng dẫn này có một khóa học video liên quan do nhóm Real Python tạo. Xem nó cùng với hướng dẫn bằng văn bản để hiểu sâu hơn. Giới thiệu về Lập trình hướng đối tượng [OOP] trong Python
🐍 Thủ thuật Python 💌
Nhận một Thủ thuật Python ngắn và hấp dẫn được gửi đến hộp thư đến của bạn vài ngày một lần. Không có thư rác bao giờ. Hủy đăng ký bất cứ lúc nào. Được quản lý bởi nhóm Real Python
Gửi cho tôi thủ thuật Python »
Giới thiệu về David Amos
David là một nhà văn, lập trình viên và nhà toán học đam mê khám phá toán học thông qua mã
» Thông tin thêm về DavidMỗi hướng dẫn tại Real Python được tạo bởi một nhóm các nhà phát triển để nó đáp ứng các tiêu chuẩn chất lượng cao của chúng tôi. Các thành viên trong nhóm đã làm việc trong hướng dẫn này là
Aldren
Joanna
Gia-cốp
Bậc thầy Kỹ năng Python trong thế giới thực Với quyền truy cập không giới hạn vào Python thực
Tham gia với chúng tôi và có quyền truy cập vào hàng nghìn hướng dẫn, khóa học video thực hành và cộng đồng các Pythonistas chuyên gia
Nâng cao kỹ năng Python của bạn »
Chuyên gia Kỹ năng Python trong thế giới thực
Với quyền truy cập không giới hạn vào Python thực
Tham gia với chúng tôi và có quyền truy cập vào hàng ngàn hướng dẫn, khóa học video thực hành và cộng đồng Pythonistas chuyên gia
Nâng cao kỹ năng Python của bạn »
Bạn nghĩ sao?
Đánh giá bài viết này
Tweet Chia sẻ Chia sẻ EmailBài học số 1 hoặc điều yêu thích mà bạn đã học được là gì?
Mẹo bình luận. Những nhận xét hữu ích nhất là những nhận xét được viết với mục đích học hỏi hoặc giúp đỡ các sinh viên khác. và nhận câu trả lời cho các câu hỏi phổ biến trong cổng thông tin hỗ trợ của chúng tôi