Sử dụng hàm super() trong lớp Python
Bài học chính
Việc sử dụng hàm super()
của Python tạo điều kiện thuận lợi cho việc gọi các phương thức trong một lớp con bằng cách truy cập vào siêu lớp của nó, từ đó nâng cao quá trình triển khai kế thừa và ghi đè phương thức một cách tinh tế.
Hàm super()
có mối liên hệ đáng kể với Thứ tự phân giải phương thức (MRO) trong Python, thứ tự chi phối trình tự trong đó các lớp tổ tiên được xem xét kỹ lưỡng về các phương thức và thuộc tính trong quá trình phân giải phương thức.
Việc sử dụng super()
bên trong hàm tạo của một lớp là một cách tiếp cận thông thường để thiết lập các đặc điểm chung trong lớp cha trong khi xác định các đặc điểm cụ thể hơn trong lớp phụ. Việc không triển khai super()
có thể dẫn đến kết quả không mong muốn, bao gồm cả việc bỏ qua việc khởi tạo thuộc tính.
Một trong những khía cạnh cơ bản của ngôn ngữ lập trình Python là mô hình Lập trình hướng đối tượng (OOP), cho phép tạo ra các mô hình đại diện cho các đối tượng trong đời thực và các mối liên kết của chúng theo cách có cấu trúc.
Trong bối cảnh lập trình bằng Python, người ta thường sử dụng tính kế thừa để sửa đổi hoặc thay thế các đặc điểm hoặc chức năng của thực thể mẹ của một lớp. Ngôn ngữ này cung cấp một cơ chế thuận tiện được gọi là hàm “super()”, cho phép thực hiện các cuộc gọi theo các phương thức của lớp cao cấp từ bên trong lớp cấp dưới.
Super() là gì và tại sao bạn cần nó?
Kế thừa từ một lớp hiện có cho phép tạo một lớp mới có thuộc tính và hành vi tương tự thông qua quá trình kế thừa. Ngoài ra, người ta có thể chọn ghi đè các phương thức cụ thể trong lớp con để cung cấp cách triển khai duy nhất của riêng chúng. Mặc dù chức năng mới này có thể được mong muốn nhưng có những trường hợp nên sử dụng đồng thời cả chức năng ban đầu và chức năng mới được triển khai. Trong những trường hợp như vậy, việc sử dụng hàm super()
cho phép tích hợp cả hai bộ khả năng vào lớp con.
Để sử dụng các thuộc tính và phương thức của siêu lớp trong lập trình hướng đối tượng, người ta có thể sử dụng hàm super()
. Hàm này đóng một vai trò quan trọng vì nó tạo điều kiện thuận lợi cho việc thực hiện kế thừa và ghi đè phương thức, là những khái niệm cơ bản trong lập trình hướng đối tượng.
super() hoạt động như thế nào?
Trong nội bộ, hành vi của hàm super()
được đan xen với khái niệm Thứ tự phân giải phương thức (MRO), một cơ chế được xác định bởi thuật toán tuyến tính hóa C3 trong Python.
Đây là cách super() hoạt động:
Khi gọi super()
trong một phương thức của lớp con trong Python, ngôn ngữ sẽ tự động xác định cả lớp hiện tại chứa phương thức gọi cũng như phiên bản của lớp đã nói được đại diện bởi self
.
⭐ Xác định siêu lớp: super() nhận hai đối số€”lớp hiện tại và phiên bản€”mà bạn không cần để vượt qua một cách rõ ràng. Nó sử dụng thông tin này để xác định siêu lớp để ủy thác lệnh gọi phương thức. Nó thực hiện điều này bằng cách kiểm tra hệ thống phân cấp lớp và MRO.
Khi một siêu lớp đã được xác định, hàm super()
cho phép gọi các phương thức của nó như thể chúng được gọi trực tiếp từ lớp con. Khả năng này tạo điều kiện thuận lợi cho cả các phương thức mở rộng và ghi đè của siêu lớp, đồng thời tận dụng cách triển khai ban đầu do siêu lớp cung cấp.
Sử dụng super() trong Trình xây dựng lớp
Việc kết hợp việc sử dụng phương thức super() trong hàm tạo của các lớp là một cách tiếp cận phổ biến, vì nó cho phép khởi tạo các thuộc tính chung giữa các lớp anh chị em trong khi vẫn cho phép các đặc điểm duy nhất ở mỗi cá thể con.
Để minh họa khái niệm kế thừa trong lập trình hướng đối tượng bằng Python, chúng ta có thể tạo một lớp “Father” đóng vai trò là lớp cơ sở cho một lớp khác có tên là “Con”. Lớp “Con” sẽ kế thừa các thuộc tính và phương thức từ lớp cha của nó là “Cha”, qua đó thể hiện cách kế thừa cho phép tái sử dụng mã và tính mô đun hóa.
class Father:
def __init__(self, first_name, last_name):
self.first_name = first_name
self.last_name = last_name
class Son(Father):
def __init__(self, first_name, last_name, age, hobby):
# Call the parent class constructor (Father)
super().__init__(first_name, last_name)
self.age = age
self.hobby = hobby
def get_info(self):
return f"Son's Name: {self.first_name} {self.last_name}, \
Son's Age: {self.age}, Son's Hobby: {self.hobby}"
# Create an instance of the Son class
son = Son("Pius", "Effiong", 25, "Playing Guitar")
# Access attributes
print(son.get_info())
Trong giới hạn của hàm tạo của lớp Son
, mệnh lệnh kêu gọi sự bảo trợ của lớp cha của nó được thực thi thông qua hành động phi thường là triệu hồi hàm super()
. Hành động then chốt này kích hoạt sự khởi đầu của hàm tạo của lớp Cha
, cung cấp hai vòng loại tối cao quý giá dưới dạng các biến first\_name
và last\_name
. Theo cách này, lớp Cha
vẫn giữ được khả năng đạt được và gán chính xác các chỉ định danh nghĩa này, bất chấp sự khởi tạo của Son
.
Trong trường hợp phương thức super()
không được gọi trong cấu trúc
...
class Son(Father):
def __init__(self, first_name, last_name, age, hobby):
self.age = age
self.hobby = hobby
...
Trong trường hợp bạn cố gắng gọi phương thức get\_info
tại thời điểm này, nó sẽ dẫn đến việc tạo ra AttributionError
, vì các thuộc tính self.first\_name
và self.last\_name
vẫn chưa được khởi tạo.
Sử dụng super() trong Phương thức lớp
Người ta có thể sử dụng hàm super() không chỉ trong giới hạn của các thủ tục xây dựng mà còn trên một loạt các phương thức khác nhau để tăng cường hoặc thay thế chức năng của cách tiếp cận phương pháp luận của lớp cha.
class Father:
def speak(self):
return "Hello from Father"
class Son(Father):
def speak(self):
# Call the parent class's speak method using super()
parent_greeting = super().speak()
return f"Hello from Son\n{parent_greeting}"
# Create an instance of the Son class
son = Son()
# Call the speak method of the Son class
son_greeting = son.speak()
print(son_greeting)
Lớp Son
trong Python được thiết kế để kế thừa các thuộc tính và phương thức từ lớp cha hoặc lớp Father
của nó, bao gồm cả phương thức speak()
. Bằng cách sử dụng hàm super().speak()
bên trong phương thức speak()
của lớp Son
, nó có thể gọi phương thức speak()
ban đầu của lớp Father
một cách hiệu quả, đồng thời kết hợp bất kỳ thông tin bổ sung hoặc tin nhắn duy nhất cho lớp Son
.
Trong trường hợp một phương thức ghi đè một phương thức khác mà không sử dụng hàm super()
được cung cấp, chức năng dự định từ lớp cha sẽ không được thực thi. Do đó, điều này có thể dẫn đến hành vi ngoài ý muốn do một phương pháp hoàn toàn mới và khác biệt thay thế chức năng ban đầu.
Tìm hiểu thứ tự giải quyết phương pháp
Thứ tự phân giải phương thức (MRO) đề cập đến hệ thống phân cấp ưu tiên xác định thứ tự mà Python sẽ tìm kiếm các phương thức và thuộc tính khi xử lý các cấu trúc lớp phức tạp liên quan đến nhiều kế thừa. Cơ chế này đảm bảo rằng phương thức thích hợp được gọi dựa trên các tùy chọn có sẵn trong các lớp cha tương ứng, từ đó giải quyết mọi sự mơ hồ tiềm ẩn phát sinh từ các định nghĩa chồng chéo.
class Nigeria():
def culture(self):
print("Nigeria's culture")
class Africa():
def culture(self):
print("Africa's culture")
Khi khởi tạo lớp Lagos và gọi phương thức văn hóa của nó, một số sự kiện xảy ra góp phần vào chức năng tổng thể của đối tượng. Quá trình thực thi mã tiến hành qua một số giai đoạn liên quan đến thao tác dữ liệu, truy xuất thông tin từ các nguồn bên ngoài và ứng dụng các thuật toán khác nhau để phân tích các khía cạnh văn hóa dựa trên các tham số đầu vào do người dùng cung cấp hoặc các giá trị mặc định được đặt trong hàm tạo. Kết quả cuối cùng là đánh giá toàn diện các thuộc tính văn hóa của thành phố cụ thể được thể hiện bằng lớp Lagos.
Đầu tiên, Python tìm kiếm phương thức culture
trong chính lớp Lagos
. Trong trường hợp phương thức này được phát hiện và có sẵn, thuật toán sẽ tiến hành gọi nó. Tuy nhiên, nếu không có phương pháp đó tồn tại hoặc không thể truy cập được thì quy trình sẽ chuyển sang giai đoạn tiếp theo.
Nếu lớp Lagos
không có phương thức culture()
, Python sẽ tìm kiếm phương thức đó trong các lớp cơ sở của hệ thống phân cấp lớp, bắt đầu từ những phương thức được liệt kê sau dấu hai chấm ( :
), được kế thừa bởi lớp lớp học’Lagos’. Trong ví dụ này, lớp Lagos
được định nghĩa là kế thừa đầu tiên từ lớp Châu Phi
và thứ hai từ lớp Nigeria
. Do đó, nếu lớp Lagos
không chứa cách triển khai phương thức culture()
của riêng nó, Python sẽ cố gắng định vị phương thức đó trong lớp Châu Phi
trước khi tìm kiếm lớp Nigeria
.
Việc tìm kiếm một phương thức dành riêng cho văn hóa trong một hệ thống phân cấp lớp nhất định tiến hành thông qua một loạt các lớp lồng nhau, với mỗi lớp tiếp theo sẽ được kiểm tra trong trường hợp tìm thấy phương thức mong muốn trong đó. Trong trường hợp phương thức này không được phát hiện ở cấp độ điều tra ban đầu, cụ thể là lớp Châu Phi, Python sẽ chuyển trọng tâm sang lớp cao nhất tiếp theo trong cấu trúc phân cấp, trong trường hợp này tương ứng với lớp Nigeria. Quá trình này lặp lại khi người ta đi xuống cây lớp, kéo dài từ chung nhất đến ít cụ thể nhất, cho đến khi phương thức được tìm kiếm không thể tìm thấy trong bất kỳ siêu lớp nào gặp phải. Vào thời điểm đó, một ngoại lệ được đưa ra để cho biết kết quả tìm kiếm không thành công.
Thứ tự phân giải phương thức (MRO) cho Lagos được hiển thị theo kiểu tuyến tính, bắt đầu từ bên trái và tiến dần về phía bên phải.
Những cạm bẫy phổ biến và cách thực hành tốt nhất
Khi sử dụng chức năng super()
, điều quan trọng là phải nhận biết được một số sai sót có thể xảy ra để đảm bảo trải nghiệm mượt mà và hiệu quả.
⭐ Hãy chú ý đến Thứ tự phân giải phương thức, đặc biệt trong trường hợp đa kế thừa. Nếu cần sử dụng đa kế thừa phức tạp, bạn nên làm quen với Thuật toán tuyến tính hóa C3 mà Python sử dụng để xác định MRO.
Nên tránh sự phụ thuộc vòng tròn trong hệ thống phân cấp lớp vì chúng có thể dẫn đến hành vi thất thường và khó dự đoán.
Khi làm việc với hệ thống phân cấp lớp phức tạp liên quan đến việc sử dụng hàm super()
, điều quan trọng là phải duy trì một cơ sở mã rõ ràng và được ghi chép đầy đủ. Điều này không chỉ đảm bảo chức năng phù hợp mà còn thúc đẩy sự hiểu biết giữa các nhà phát triển đồng nghiệp, những người có thể cần làm việc hoặc sửa đổi mã trong tương lai. Bằng cách cung cấp các nhận xét ngắn gọn nhưng đầy đủ thông tin, bạn có thể nâng cao khả năng đọc và bảo trì dự án của mình, tạo điều kiện hợp tác và giảm các lỗi hoặc nhầm lẫn tiềm ẩn.
Sử dụng super() đúng cách
Việc sử dụng hàm super()
của Python thể hiện một khía cạnh không thể thiếu trong mô hình lập trình hướng đối tượng của nó, đặc biệt liên quan đến việc hỗ trợ tính kế thừa và ghi đè phương thức. Nắm bắt được những điều phức tạp liên quan đến thực thể chức năng này và tuân thủ các phương pháp hay nhất đã được thiết lập cho phép phát triển các ứng dụng phần mềm bền bỉ và hiệu quả hơn trong hệ sinh thái Python.