Fungsi kelebihan beban di python?


91

Apakah mungkin memiliki fungsi yang kelebihan beban dengan Python? Dalam C # saya akan melakukan sesuatu seperti

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

dan kemudian ketika saya memanggil fungsi itu akan membedakan antara keduanya berdasarkan jumlah argumen. Apakah mungkin melakukan sesuatu yang serupa dengan Python?


Sepertinya ini adalah postingan duplikat. Juga tolong jangan tandai sebagai C # karena pertanyaannya tidak ada hubungannya dengan C #. function-overloading-in-python-missing
Jethro


Jawaban:


103

EDIT Untuk fungsi generik pengiriman tunggal baru di Python 3.4, lihat http://www.python.org/dev/peps/pep-0443/

Anda biasanya tidak perlu membebani fungsi dengan Python. Python diketik secara dinamis , dan mendukung argumen opsional untuk fungsi.

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
Tetapi perhatikan bahwa memanggil fungsi yang berbeda berdasarkan jenis argumen jauh lebih sulit (meskipun bukan tidak mungkin).
Andrew Jaffe

9
Nah, ada perbedaan antara overloading / polymorphism dan conditionals. Apakah maksud Anda kita tidak membutuhkan polimorfisme karena kita memiliki kondisional?
Val

1
@Val Saya katakan, pada dasarnya, bahwa dalam bahasa yang diketik secara dinamis Anda tidak perlu kelebihan beban sebagai fitur bahasa karena Anda dapat dengan mudah menirunya dalam kode, sehingga bisa mendapatkan polimorfisme dengan cara itu.
agf

1
@Val Saya mengatakan bahwa antara argumen opsional dan tipe dinamis seperti yang Anda miliki dengan Python, Anda tidak perlu metode gaya Java overloading untuk mencapai polimorfisme.
agf

3
@navidoo Saya berpendapat itu bukan ide yang baik - fungsi tidak boleh mengembalikan jenis hal yang sama sekali berbeda. Namun, Anda selalu dapat mendefinisikan fungsi generator lokal di dalam fungsi utama, memanggilnya, dan mengembalikan generator yang dihasilkan - dari luar akan sama seperti jika fungsi utama adalah generator. Contoh di sini.
agf

50

di python normal Anda tidak dapat melakukan apa yang Anda inginkan. ada dua perkiraan yang mirip:

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

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

namun, jika Anda benar - benar ingin melakukan ini, Anda pasti dapat membuatnya berhasil (dengan risiko menyinggung kaum tradisionalis; o). singkatnya, Anda akan menulis wrapper(*args)fungsi yang memeriksa jumlah argumen dan delegasi yang sesuai. "hack" semacam ini biasanya dilakukan melalui dekorator. dalam hal ini Anda dapat mencapai sesuatu seperti:

from typing import overload

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

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

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

dan Anda akan mengimplementasikan ini dengan membuat overload(first_fn) fungsi (atau konstruktor) mengembalikan objek yang dapat dipanggil di mana __call__(*args) metode melakukan delegasi yang dijelaskan di atas dan overload(another_fn) metode tersebut menambahkan fungsi tambahan yang dapat didelegasikan.

Anda dapat melihat contoh dari sesuatu yang serupa di sini http://acooke.org/pytyp/pytyp.spec.dispatch.html tetapi itu membebani metode menurut jenis. itu pendekatan yang sangat mirip ...

UPDATE: dan sesuatu yang serupa (menggunakan tipe argumen) ditambahkan ke python 3 - http://www.python.org/dev/peps/pep-0443/


The rangebuiltin menggunakan overload, sehingga itu benar-benar hack? github.com/python/typeshed/blob/master/stdlib/2and3/…
CptJero

9

Iya itu mungkin. Saya menulis kode di bawah ini dengan Python 3.2.1:

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

Pemakaian:

myfunction=overload(no_arg_func, one_arg_func, two_arg_func)

Perhatikan bahwa lambda yang dikembalikan oleh overloadfungsi pilih fungsi yang akan dipanggil bergantung pada jumlah argumen tanpa nama .

Solusinya tidak sempurna, tetapi saat ini saya tidak dapat menulis sesuatu yang lebih baik.


1

Tidak mungkin secara langsung. Anda dapat menggunakan pemeriksaan tipe eksplisit pada argumen yang diberikan, meskipun hal ini umumnya tidak disukai.

Python itu dinamis. Jika Anda tidak yakin apa yang dapat dilakukan suatu objek, coba saja: dan panggil metode di atasnya, lalu kecuali: error.

Jika Anda tidak perlu membebani berdasarkan jenis tetapi hanya pada jumlah argumen, gunakan argumen kata kunci.


3
Saya tidak berpikir dia tahu tentang argumen opsional.
agf

0

metode overloading rumit di python. Namun, mungkin ada penggunaan untuk meneruskan dict, list atau variabel primitif.

Saya telah mencoba sesuatu untuk kasus penggunaan saya, ini dapat membantu di sini untuk memahami orang-orang untuk membebani metode.

Mari kita ambil contoh penggunaan di salah satu utas stackoverflow:

metode kelebihan beban kelas dengan memanggil metode dari kelas yang berbeda.

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

teruskan argumen dari kelas jarak jauh:

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

ATAU add_bullet(sprite = 'test', start=Yes,headto={'lat':10.6666,'long':10.6666},speed=['10','20,'30']}

Jadi, penanganan sedang dicapai untuk daftar, kamus atau variabel primitif dari metode overloading.

cobalah untuk kode Anda

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.