Các chức năng bị quá tải trong python?


91

Có thể có các hàm quá tải trong Python không? Trong C # tôi sẽ làm một cái gì đó như

void myfunction (int first, string second)
{
//some code
}
void myfunction (int first, string second , float third)
{
//some different code
}

và sau đó khi tôi gọi hàm, nó sẽ phân biệt giữa hai hàm dựa trên số lượng đối số. Có thể làm điều gì đó tương tự trong Python không?


Đây dường như là một bài viết có thể trùng lặp. Cũng xin đừng gắn cờ là C # vì câu hỏi không liên quan đến C #. hàm quá tải-in-python-thiếu
Jethro


Câu trả lời:


103

CHỈNH SỬA Đối với các hàm chung điều hành đơn mới trong Python 3.4, hãy xem http://www.python.org/dev/peps/pep-0443/

Nói chung, bạn không cần phải quá tải các hàm trong Python. Python được gõ động và hỗ trợ các đối số tùy chọn cho các hàm.

def myfunction(first, second, third = None):
    if third is None:
        #just use first and second
    else:
        #use all three

myfunction(1, 2) # third will be None, so enter the 'if' clause
myfunction(3, 4, 5) # third isn't None, it's 5, so enter the 'else' clause

3
Nhưng lưu ý rằng việc gọi các hàm khác nhau dựa trên kiểu của các đối số sẽ khó hơn nhiều (mặc dù không phải là không thể).
Andrew Jaffe

9
Chà, có sự khác biệt giữa quá tải / đa hình và điều kiện. Bạn có nghĩa là chúng ta không cần đa hình vì chúng ta có các điều kiện?
Val

1
@Val Tôi đang nói, về cơ bản, trong một ngôn ngữ được nhập động, bạn không cần quá tải như một tính năng ngôn ngữ vì bạn có thể mô phỏng nó trong mã một cách đáng kể và do đó, có thể có được tính đa hình theo cách đó.
agf

1
@Val Tôi đang nói rằng giữa các đối số tùy chọn và kiểu động theo cách bạn có chúng trong Python, bạn không cần nạp chồng phương thức kiểu Java để đạt được tính đa hình.
AGF

3
@navidoo Tôi sẽ tranh luận rằng đó không phải là một ý kiến ​​hay - một hàm không hoàn toàn trả về các loại thứ khác nhau. Tuy nhiên, bạn luôn có thể xác định một hàm tạo cục bộ bên trong hàm chính, gọi nó và trả về bộ tạo kết quả - từ bên ngoài, nó sẽ giống như nếu hàm chính là một bộ tạo. Ví dụ ở đây.
agf

50

trong python bình thường, bạn không thể làm những gì bạn muốn. có hai giá trị gần đúng:

def myfunction(first, second, *args):
    # args is a tuple of extra arguments

def myfunction(first, second, third=None):
    # third is optional

tuy nhiên, nếu bạn thực sự muốn làm điều này, bạn chắc chắn có thể làm cho nó hoạt động (có nguy cơ xúc phạm những người theo chủ nghĩa truyền thống; o). trong ngắn hạn, bạn sẽ viết một wrapper(*args)hàm kiểm tra số lượng đối số và đại biểu có phù hợp không. loại "hack" này thường được thực hiện thông qua trình trang trí. trong trường hợp này, bạn có thể đạt được điều gì đó như:

from typing import overload

@overload
def myfunction(first):
    ....

@myfunction.overload
def myfunction(first, second):
    ....

@myfunction.overload
def myfunction(first, second, third):
    ....

và bạn sẽ triển khai điều này bằng cách làm cho overload(first_fn) hàm (hoặc hàm tạo) trả về một đối tượng có thể gọi được trong đó __call__(*args) phương thức ủy quyền đã giải thích ở trên và overload(another_fn) phương thức này thêm các chức năng bổ sung có thể được ủy quyền.

bạn có thể xem một ví dụ về điều gì đó tương tự tại đây http://acooke.org/pytyp/pytyp.spec.dispatch.html nhưng đó là quá tải các phương thức theo loại. đó là một cách tiếp cận rất giống ...

CẬP NHẬT: và một cái gì đó tương tự (sử dụng kiểu đối số) đang được thêm vào python 3 - http://www.python.org/dev/peps/pep-0443/


Nội rangetrang sử dụng quá tải, vì vậy nó thực sự là một hack? github.com/python/typeshed/blob/master/stdlib/2and3/…
CptJero

9

Vâng nó có thể. Tôi đã viết mã bên dưới bằng Python 3.2.1:

def overload(*functions):
    return lambda *args, **kwargs: functions[len(args)](*args, **kwargs)

Sử dụng:

myfunction=overload(no_arg_func, one_arg_func, two_arg_func)

Lưu ý rằng lambda được trả về bởi các overloadhàm chọn hàm để gọi tùy thuộc vào số lượng các đối số không được đặt tên .

Giải pháp không hoàn hảo, nhưng hiện tại tôi không thể viết gì tốt hơn.


1

Không thể trực tiếp. Bạn có thể sử dụng kiểm tra kiểu rõ ràng đối với các đối số được đưa ra, mặc dù điều này thường bị phản đối.

Python là động. Nếu bạn không chắc một đối tượng có thể làm gì, chỉ cần thử: và gọi một phương thức trên đó, sau đó ngoại trừ: lỗi.

Nếu bạn không cần quá tải dựa trên loại mà chỉ dựa trên số lượng đối số, hãy sử dụng đối số từ khóa.


3
Tôi không nghĩ rằng anh ấy biết về các đối số tùy chọn.
agf

0

quá tải các phương thức phức tạp trong python. Tuy nhiên, có thể có cách sử dụng truyền các biến dict, list hoặc nguyên thủy.

Tôi đã thử một cái gì đó cho các trường hợp sử dụng của mình, điều này có thể giúp ở đây để hiểu mọi người quá tải các phương thức.

Hãy lấy ví dụ sử dụng trong một trong các chuỗi stackoverflow:

một phương thức nạp chồng lớp với việc gọi các phương thức từ các lớp khác nhau.

def add_bullet(sprite=None, start=None, headto=None, spead=None, acceleration=None):

truyền các đối số từ lớp từ xa:

add_bullet(sprite = 'test', start=Yes,headto={'lat':10.6666,'long':10.6666},accelaration=10.6}

HOẶC LÀ add_bullet(sprite = 'test', start=Yes,headto={'lat':10.6666,'long':10.6666},speed=['10','20,'30']}

Vì vậy, việc xử lý đang được thực hiện đối với danh sách, Từ điển hoặc các biến nguyên thủy từ quá trình nạp chồng phương thức.

thử nó cho mã của bạn

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.