Từ quá tải có nghĩa là nạp quá nhiều vào hoặc lên một thứ gì đó, chẳng hạn như quá tải điện làm chập mạch. Theo cách tương tự, Quá tải đề cập đến khả năng một đối tượng có thể có nhiều hành vi. Quá tải là một trong những tính năng vượt trội của OOPS
Tại sao chúng ta nên sử dụng Overloading?Quá tải hàm là khả năng có nhiều hàm có cùng tên nhưng có chữ ký/cách triển khai khác nhau. Khi một hàm bị quá tải
def area[radius]:
return 3.14 * radius ** 2
>>> locals[]
{
...
'area': ,
...
}
1 được gọi, bộ thực thi trước tiên sẽ đánh giá các đối số/tham số được truyền cho lệnh gọi hàm và đánh giá bằng cách này sẽ gọi triển khai tương ứngint area[int length, int breadth] {
return length * breadth;
}
float area[int radius] {
return 3.14 * radius * radius;
}
Trong ví dụ trên [được viết bằng C++], hàm
def area[radius]:
return 3.14 * radius ** 2
>>> locals[]
{
...
'area': ,
...
}
2 bị quá tải với hai lần triển khai; . Khi chúng ta gọi hàm def area[radius]:
return 3.14 * radius ** 2
>>> locals[]
{
...
'area': ,
...
}
2 như def area[radius]:
return 3.14 * radius ** 2
>>> locals[]
{
...
'area': ,
...
}
4, nó gọi hàm thứ hai trong khi def area[radius]:
return 3.14 * radius ** 2
>>> locals[]
{
...
'area': ,
...
}
5 gọi hàm đầu tiênTại sao không có chức năng quá tải trong Python?
Python không hỗ trợ nạp chồng hàm. Khi chúng ta định nghĩa nhiều hàm có cùng tên, hàm sau luôn ghi đè lên hàm trước và do đó, trong không gian tên, sẽ luôn có một mục duy nhất đối với mỗi tên hàm. Chúng tôi thấy những gì tồn tại trong các không gian tên Python bằng cách gọi các hàm
def area[radius]:
return 3.14 * radius ** 2
>>> locals[]
{
...
'area': ,
...
}
6 và def area[radius]:
return 3.14 * radius ** 2
>>> locals[]
{
...
'area': ,
...
}
7, trả về không gian tên cục bộ và toàn cầu tương ứngdef area[radius]:
return 3.14 * radius ** 2
>>> locals[]
{
...
'area': ,
...
}
Gọi hàm
def area[radius]:
return 3.14 * radius ** 2
>>> locals[]
{
...
'area': ,
...
}
6 sau khi xác định hàm, chúng ta thấy rằng nó trả về một từ điển gồm tất cả các biến được xác định trong không gian tên cục bộ. Chìa khóa của từ điển là tên của biến và giá trị là tham chiếu/giá trị của biến đó. Khi bộ thực thi gặp một hàm khác có cùng tên, nó sẽ cập nhật mục nhập trong không gian tên cục bộ và do đó loại bỏ khả năng hai hàm cùng tồn tại. Do đó python không hỗ trợ Nạp chồng hàm. Đó là quyết định thiết kế được đưa ra trong khi tạo ngôn ngữ nhưng điều này không ngăn chúng tôi thực hiện nó, vì vậy hãy quá tải một số chức năngTriển khai nạp chồng hàm trong PythonChúng tôi biết cách Python quản lý các không gian tên và nếu chúng tôi muốn thực hiện quá tải chức năng, chúng tôi sẽ cần phải
- quản lý các định nghĩa hàm trong một không gian tên ảo được duy trì
- tìm cách gọi hàm thích hợp theo các đối số được truyền cho nó
Để đơn giản, chúng ta sẽ thực hiện nạp chồng hàm trong đó các hàm có cùng tên được phân biệt bằng số đối số mà nó chấp nhận
Bao hàm chức năng
Chúng tôi tạo một lớp có tên là
def area[radius]:
return 3.14 * radius ** 2
>>> locals[]
{
...
'area': ,
...
}
9 bao hàm bất kỳ chức năng nào và làm cho nó có thể gọi được thông qua một phương thức int area[int length, int breadth] {
return length * breadth;
}
float area[int radius] {
return 3.14 * radius * radius;
}
10 bị ghi đè và cũng hiển thị một phương thức có tên là int area[int length, int breadth] {
return length * breadth;
}
float area[int radius] {
return 3.14 * radius * radius;
}
11 trả về một bộ làm cho chức năng này trở thành duy nhất trong toàn bộ cơ sở mãint area[int length, int breadth] {
return length * breadth;
}
float area[int radius] {
return 3.14 * radius * radius;
}
1Trong đoạn mã trên, hàm
int area[int length, int breadth] {
return length * breadth;
}
float area[int radius] {
return 3.14 * radius * radius;
}
11 trả về một bộ xác định duy nhất hàm trong cơ sở mã và giữ- mô-đun chức năng
- lớp mà hàm thuộc về
- tên của chức năng
- số đối số mà hàm chấp nhận
Phương thức
int area[int length, int breadth] {
return length * breadth;
}
float area[int radius] {
return 3.14 * radius * radius;
}
10 bị ghi đè gọi hàm được bao bọc và trả về giá trị được tính toán [hiện tại không có gì lạ mắt ở đây]. Điều này làm cho thể hiện có thể gọi được giống như chức năng và nó hoạt động chính xác như chức năng được bao bọcint area[int length, int breadth] {
return length * breadth;
}
float area[int radius] {
return 3.14 * radius * radius;
}
6Trong ví dụ trên, hàm
def area[radius]:
return 3.14 * radius ** 2
>>> locals[]
{
...
'area': ,
...
}
2 được bọc trong def area[radius]:
return 3.14 * radius ** 2
>>> locals[]
{
...
'area': ,
...
}
9 được khởi tạo trong int area[int length, int breadth] {
return length * breadth;
}
float area[int radius] {
return 3.14 * radius * radius;
}
16. int area[int length, int breadth] {
return length * breadth;
}
float area[int radius] {
return 3.14 * radius * radius;
}
17 trả về bộ dữ liệu có phần tử đầu tiên là tên mô-đun int area[int length, int breadth] {
return length * breadth;
}
float area[int radius] {
return 3.14 * radius * radius;
}
18, phần tử thứ hai là lớp int area[int length, int breadth] {
return length * breadth;
}
float area[int radius] {
return 3.14 * radius * radius;
}
19, phần tử thứ ba là tên hàm def area[radius]:
return 3.14 * radius ** 2
>>> locals[]
{
...
'area': ,
...
}
2 trong khi phần tử thứ tư là số đối số mà hàm def area[radius]:
return 3.14 * radius ** 2
>>> locals[]
{
...
'area': ,
...
}
2 chấp nhận là int area[int length, int breadth] {
return length * breadth;
}
float area[int radius] {
return 3.14 * radius * radius;
}
62Ví dụ này cũng cho thấy cách chúng ta có thể gọi thể hiện
int area[int length, int breadth] {
return length * breadth;
}
float area[int radius] {
return 3.14 * radius * radius;
}
16, giống như hàm def area[radius]:
return 3.14 * radius ** 2
>>> locals[]
{
...
'area': ,
...
}
2 thông thường, với các đối số int area[int length, int breadth] {
return length * breadth;
}
float area[int radius] {
return 3.14 * radius * radius;
}
65 và int area[int length, int breadth] {
return length * breadth;
}
float area[int radius] {
return 3.14 * radius * radius;
}
66 và nhận được phản hồi int area[int length, int breadth] {
return length * breadth;
}
float area[int radius] {
return 3.14 * radius * radius;
}
67, chính xác là những gì chúng ta sẽ nhận được mà chúng ta sẽ gọi là def area[radius]:
return 3.14 * radius ** 2
>>> locals[]
{
...
'area': ,
...
}
5. Hành vi này sẽ có ích trong giai đoạn sau khi chúng ta chơi với các nhà trang tríXây dựng Namespace ảo
Không gian tên ảo, chúng tôi xây dựng ở đây, sẽ lưu trữ tất cả các chức năng chúng tôi thu thập được trong giai đoạn định nghĩa. Vì chỉ có một không gian tên/cơ quan đăng ký nên chúng tôi tạo một lớp đơn chứa các hàm trong từ điển có khóa không chỉ là tên hàm mà là bộ chúng tôi nhận được từ hàm
int area[int length, int breadth] {
return length * breadth;
}
float area[int radius] {
return 3.14 * radius * radius;
}
11, chứa các phần tử xác định duy nhất hàm trong toàn bộ cơ sở mã. Thông qua đó, chúng tôi sẽ có thể giữ các chức năng trong sổ đăng ký ngay cả khi chúng có cùng tên [nhưng các đối số khác nhau] và do đó tạo điều kiện cho quá tải chức năngdef area[radius]:
return 3.14 * radius ** 2
>>> locals[]
{
...
'area': ,
...
}
3def area[radius]:
return 3.14 * radius ** 2
>>> locals[]
{
...
'area': ,
...
}
30 có một phương thức def area[radius]:
return 3.14 * radius ** 2
>>> locals[]
{
...
'area': ,
...
}
31 lấy hàm def area[radius]:
return 3.14 * radius ** 2
>>> locals[]
{
...
'area': ,
...
}
1 làm đối số, tạo một khóa duy nhất cho nó, lưu trữ nó trong từ điển và trả về def area[radius]:
return 3.14 * radius ** 2
>>> locals[]
{
...
'area': ,
...
}
1 được bao bọc trong một thể hiện của def area[radius]:
return 3.14 * radius ** 2
>>> locals[]
{
...
'area': ,
...
}
9. Điều này có nghĩa là giá trị trả về từ hàm def area[radius]:
return 3.14 * radius ** 2
>>> locals[]
{
...
'area': ,
...
}
31 cũng có thể gọi được và [cho đến bây giờ] hành vi của nó hoàn toàn giống với hàm bọc def area[radius]:
return 3.14 * radius ** 2
>>> locals[]
{
...
'area': ,
...
}
1def area[radius]:
return 3.14 * radius ** 2
>>> locals[]
{
...
'area': ,
...
}
1Sử dụng đồ trang trí như một cái móc
Bây giờ chúng ta đã xác định một không gian tên ảo với khả năng đăng ký một hàm, chúng ta cần một hook được gọi trong khi định nghĩa hàm; . Trong Python, một trình trang trí bao bọc một chức năng và cho phép chúng tôi thêm chức năng mới vào chức năng hiện có mà không sửa đổi cấu trúc của nó. Một trình trang trí chấp nhận hàm bao bọc
def area[radius]:
return 3.14 * radius ** 2
>>> locals[]
{
...
'area': ,
...
}
1 làm đối số và trả về một hàm khác được gọi thay thế. Hàm này chấp nhận def area[radius]:
return 3.14 * radius ** 2
>>> locals[]
{
...
'area': ,
...
}
38 và def area[radius]:
return 3.14 * radius ** 2
>>> locals[]
{
...
'area': ,
...
}
39 được truyền trong khi gọi hàm và trả về giá trịMột trình trang trí mẫu có thời gian thực thi một chức năng được trình bày bên dưới
def area[radius]:
return 3.14 * radius ** 2
>>> locals[]
{
...
'area': ,
...
}
5Trong ví dụ trên, chúng tôi xác định một trình trang trí có tên là
def area[radius]:
return 3.14 * radius ** 2
>>> locals[]
{
...
'area': ,
...
}
10 bao bọc hàm def area[radius]:
return 3.14 * radius ** 2
>>> locals[]
{
...
'area': ,
...
}
2 và in trên def area[radius]:
return 3.14 * radius ** 2
>>> locals[]
{
...
'area': ,
...
}
12 thời gian thực hiệnHàm trang trí
def area[radius]:
return 3.14 * radius ** 2
>>> locals[]
{
...
'area': ,
...
}
10 được gọi mỗi lần [để nó bao bọc hàm được trang trí và lưu trữ hàm bao bọc mới này trong không gian tên cục bộ hoặc toàn cầu của Python], trình thông dịch gặp một định nghĩa hàm và đối với chúng tôi, đó là một cái móc lý tưởng để đăng ký hàm . Do đó, chúng tôi tạo trình trang trí có tên là def area[radius]:
return 3.14 * radius ** 2
>>> locals[]
{
...
'area': ,
...
}
14 để đăng ký hàm trong không gian tên ảo và trả về một hàm có thể gọi được để gọidef area[radius]:
return 3.14 * radius ** 2
>>> locals[]
{
...
'area': ,
...
}
1Trình trang trí
def area[radius]:
return 3.14 * radius ** 2
>>> locals[]
{
...
'area': ,
...
}
14 trả về một thể hiện của def area[radius]:
return 3.14 * radius ** 2
>>> locals[]
{
...
'area': ,
...
}
9, như được trả về bởi def area[radius]:
return 3.14 * radius ** 2
>>> locals[]
{
...
'area': ,
...
}
17 chức năng của không gian tên. Bây giờ, bất cứ khi nào hàm [được trang trí bởi def area[radius]:
return 3.14 * radius ** 2
>>> locals[]
{
...
'area': ,
...
}
14] được gọi, nó sẽ gọi hàm được trả về bởi hàm def area[radius]:
return 3.14 * radius ** 2
>>> locals[]
{
...
'area': ,
...
}
17 - một thể hiện của def area[radius]:
return 3.14 * radius ** 2
>>> locals[]
{
...
'area': ,
...
}
9 và phương thức int area[int length, int breadth] {
return length * breadth;
}
float area[int radius] {
return 3.14 * radius * radius;
}
10 được thực thi với def area[radius]:
return 3.14 * radius ** 2
>>> locals[]
{
...
'area': ,
...
}
38 và def area[radius]:
return 3.14 * radius ** 2
>>> locals[]
{
...
'area': ,
...
}
39 đã chỉ định được truyền trong khi gọi. Bây giờ những gì còn lại là triển khai phương thức int area[int length, int breadth] {
return length * breadth;
}
float area[int radius] {
return 3.14 * radius * radius;
}
10 trong lớp def area[radius]:
return 3.14 * radius ** 2
>>> locals[]
{
...
'area': ,
...
}
9 sao cho nó gọi hàm thích hợp với các đối số được truyền trong khi gọiTìm đúng chức năng từ không gian tên
Phạm vi định hướng, ngoài tên và lớp mô-đun thông thường, là số lượng đối số mà hàm chấp nhận và do đó chúng tôi định nghĩa một phương thức có tên là
def area[radius]:
return 3.14 * radius ** 2
>>> locals[]
{
...
'area': ,
...
}
56 trong không gian tên ảo của chúng tôi, phương thức này chấp nhận hàm từ không gian tên của python [sẽ là định nghĩa cuối cùng cho Vai trò của hàm
def area[radius]:
return 3.14 * radius ** 2
>>> locals[]
{
...
'area': ,
...
}
56 này là quyết định việc triển khai hàm nào [nếu bị quá tải] sẽ được gọi. Quá trình lấy hàm thích hợp khá đơn giản - từ hàm và các đối số tạo khóa duy nhất bằng cách sử dụng hàm int area[int length, int breadth] {
return length * breadth;
}
float area[int radius] {
return 3.14 * radius * radius;
}
11 [như đã thực hiện khi đăng ký] và xem liệu nó có tồn tại trong sổ đăng ký hàm hay không; def area[radius]:
return 3.14 * radius ** 2
>>> locals[]
{
...
'area': ,
...
}
6Hàm
def area[radius]:
return 3.14 * radius ** 2
>>> locals[]
{
...
'area': ,
...
}
56 tạo một thể hiện của def area[radius]:
return 3.14 * radius ** 2
>>> locals[]
{
...
'area': ,
...
}
9 chỉ để nó có thể sử dụng hàm int area[int length, int breadth] {
return length * breadth;
}
float area[int radius] {
return 3.14 * radius * radius;
}
11 để lấy một khóa duy nhất và không sao chép logic. Sau đó, khóa được sử dụng để tìm nạp chức năng thích hợp từ sổ đăng ký chức năngGọi hàm
Như đã nêu ở trên, phương thức
int area[int length, int breadth] {
return length * breadth;
}
float area[int radius] {
return 3.14 * radius * radius;
}
10 trong lớp def area[radius]:
return 3.14 * radius ** 2
>>> locals[]
{
...
'area': ,
...
}
9 được gọi mỗi khi một hàm được trang trí bằng một trình trang trí def area[radius]:
return 3.14 * radius ** 2
>>> locals[]
{
...
'area': ,
...
}
14 được gọi. Chúng tôi sử dụng chức năng này để tìm nạp chức năng thích hợp bằng cách sử dụng chức năng def area[radius]:
return 3.14 * radius ** 2
>>> locals[]
{
...
'area': ,
...
}
56 của không gian tên và gọi triển khai bắt buộc của chức năng quá tải. Phương pháp int area[int length, int breadth] {
return length * breadth;
}
float area[int radius] {
return 3.14 * radius * radius;
}
10 được thực hiện như saudef area[radius]:
return 3.14 * radius ** 2
>>> locals[]
{
...
'area': ,
...
}
5Phương thức tìm nạp hàm thích hợp từ không gian tên ảo và nếu nó không tìm thấy bất kỳ hàm nào, nó sẽ đưa ra một
def area[radius]:
return 3.14 * radius ** 2
>>> locals[]
{
...
'area': ,
...
}
17 và nếu có, nó sẽ gọi hàm đó và trả về giá trịQuá tải chức năng trong hành động
Khi tất cả mã được đặt vào vị trí, chúng tôi xác định hai chức năng có tên là
def area[radius]:
return 3.14 * radius ** 2
>>> locals[]
{
...
'area': ,
...
}
2. một tính diện tích hình chữ nhật và một tính diện tích hình tròn. Cả hai chức năng được xác định bên dưới và được trang trí bằng một trình trang trí def area[radius]:
return 3.14 * radius ** 2
>>> locals[]
{
...
'area': ,
...
}
14def area[radius]:
return 3.14 * radius ** 2
>>> locals[]
{
...
'area': ,
...
}
0Khi chúng ta gọi
def area[radius]:
return 3.14 * radius ** 2
>>> locals[]
{
...
'area': ,
...
}
2 với một đối số, nó trả về diện tích hình tròn và khi chúng ta truyền hai đối số, nó gọi hàm tính diện tích hình chữ nhật, do đó làm quá tải hàm def area[radius]:
return 3.14 * radius ** 2
>>> locals[]
{
...
'area': ,
...
}
2. Bạn có thể tìm thấy toàn bộ bản demo đang hoạt động tại đâyPython không hỗ trợ nạp chồng hàm nhưng bằng cách sử dụng các cấu trúc ngôn ngữ phổ biến, chúng tôi đã hack một giải pháp cho nó. Chúng tôi đã sử dụng các trình trang trí và một không gian tên do người dùng duy trì để quá tải các hàm và sử dụng số lượng đối số làm yếu tố định hướng. Chúng ta cũng có thể sử dụng các kiểu dữ liệu [được xác định trong trình trang trí] của các đối số để định hướng - cho phép các hàm có cùng số lượng đối số nhưng khác kiểu quá tải. Độ chi tiết của tình trạng quá tải chỉ bị giới hạn bởi chức năng
def area[radius]:
return 3.14 * radius ** 2
>>> locals[]
{
...
'area': ,
...
}
62 và trí tưởng tượng của chúng tôi. Một cách tiếp cận gọn gàng hơn, sạch sẽ hơn và hiệu quả hơn cũng có thể thực hiện được với các cấu trúc trên, vì vậy hãy thoải mái triển khai một cách tiếp cận và tweet cho tôi @arpit_bhayani, tôi sẽ rất vui khi biết bạn đã làm gì với nóBài viết này ban đầu được xuất bản trên blog của tôi - Hàm quá tải trong Python
Nếu bạn thích những gì bạn đọc, hãy đăng ký nhận bản tin của tôi và nhận bài đăng được gửi trực tiếp vào hộp thư đến của bạn và gửi lời cảm ơn tới tôi @arpit_bhayani
con trăn
Bài báo cáo
Thưởng thức bài viết này?
10
Chia sẻ
Arpit Bhayani
Phần phụ trợ @Unacademy • Dữ liệu @Amazon • Nền tảng @Practo. Viết về Ngôn ngữ bên trong và Toán học trong Khoa học Máy tính
Tôi là một lập trình viên đam mê, đam mê viết mã, thiết kế, khởi nghiệp và công nghệ. Hiện tại tôi đang làm việc tại Amazon với vị trí Kỹ sư phát triển phần mềm 2. Trước Amazon, tôi đang làm việc cho một công ty khởi nghiệp về chăm sóc sức khỏe tên là Practo, nơi tôi độc thân
Theo
Khám phá và đọc thêm các bài viết từ Arpit Bhayani
bắt đầu
Thưởng thức bài viết này?
Để lại một lượt thích và bình luận cho Arpit
10
Gửi đi
yotamolik
một năm trước
có thể nó giống một câu hỏi triết học hơn - nhưng tại sao Python không bị quá tải ngay từ đầu?
Hồi đáp
Daniel Riggs
một năm trước
Kể từ trăn 3. 8, một trình trang trí quá tải có sẵn trong thư viện tiêu chuẩn.
Ngoài ra còn có funcools. singledispatch có thể làm điều tương tự. https. // tài liệu. con trăn. org/3/library/funcools. html
Tôi không chắc liệu chúng có bao gồm mọi thứ bạn viết ở đây hay không, nhưng sẽ rất tuyệt nếu nói về lý do tại sao các tùy chọn thư viện tiêu chuẩn này không đủ [nếu không]