Python'da aşırı yüklenmiş fonksiyonlar?


91

Python'da aşırı yüklenmiş fonksiyonlara sahip olmak mümkün mü? C # 'da şöyle bir şey yapardım

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

ve sonra işlevi çağırdığımda, argüman sayısına bağlı olarak ikisi arasında ayrım yapardı. Python'da benzer bir şey yapmak mümkün mü?


Bu, olası bir yinelenen gönderi gibi görünüyor. Ayrıca sorunun C # ile ilgisi olmadığı için lütfen C # olarak işaretlemeyin. python'da fonksiyon aşırı yükleme eksik
Jethro


Yanıtlar:


103

DÜZENLE Python 3.4'teki yeni tek dağıtım genel işlevleri için bkz. Http://www.python.org/dev/peps/pep-0443/

Python'da genellikle işlevleri aşırı yüklemenize gerek yoktur. Python dinamik olarak yazılmıştır ve fonksiyonlara isteğe bağlı argümanları destekler.

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
Ancak , argümanların türüne göre farklı işlevleri çağırmanın çok daha zor olduğunu unutmayın (imkansız olmasa da).
Andrew Jaffe

9
Şey, aşırı yükleme / çok biçimlilik ve koşullu ifadeler arasında bir fark vardır. Koşullara sahip olduğumuz için polimorfizmaya ihtiyacımız olmadığını mı söylüyorsun?
Val

1
@Val Temel olarak, dinamik olarak yazılmış bir dilde dil özelliği olarak aşırı yüklemeye ihtiyacınız olmadığını söylüyorum, çünkü onu kodda önemsiz bir şekilde taklit edebilirsiniz ve böylece çok biçimlilik elde edebilirsiniz.
agf

1
@Val Python'da isteğe bağlı argümanlar ve dinamik türler arasında polimorfizm elde etmek için Java tarzı yöntem aşırı yüklemesine ihtiyacınız olmadığını söylüyorum.
agf

3
@navidoo Bunun iyi bir fikir olmadığını savunabilirim - bir işlev tamamen farklı türde şeyler döndürmemelidir. Bununla birlikte, ana işlevin içinde her zaman yerel bir üretici işlevi tanımlayabilir, çağırabilir ve elde edilen oluşturucuyu geri getirebilirsiniz - dışarıdan ana işlev bir üreteçmiş gibi aynı olacaktır. Örnek burada.
agf

50

normal python'da istediğinizi yapamazsınız. iki yakın tahmin vardır:

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

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

ancak, eğer bunu gerçekten yapmak istiyorsanız, kesinlikle çalışmasını sağlayabilirsiniz (gelenekçileri rencide etme riskiyle; o). kısaca, wrapper(*args)argüman ve temsilci sayısını uygun şekilde kontrol eden bir işlev yazarsınız . bu tür bir "hack" genellikle dekoratörler aracılığıyla yapılır. bu durumda aşağıdaki gibi bir şey elde edebilirsiniz:

from typing import overload

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

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

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

ve yaparak bu uygulamaya ediyorum overload(first_fn) fonksiyonu (veya kurucu) bir çağrılabilir nesneyi döndürmek __call__(*args) yöntem heyet yukarıda açıklandığı ve does overload(another_fn) yöntem devredilebilir edilebilir ekstra fonksiyonlar ekler.

http://acooke.org/pytyp/pytyp.spec.dispatch.html burada benzer bir örnek görebilirsiniz, ancak bu, yöntemleri türe göre aşırı yüklemektir. çok benzer bir yaklaşım ...

GÜNCELLEME: ve benzer bir şey (bağımsız değişken türleri kullanılarak) python 3'e ekleniyor - http://www.python.org/dev/peps/pep-0443/


rangeBuiltin yüzden gerçekten kesmek, aşırı kullanır? github.com/python/typeshed/blob/master/stdlib/2and3/…
CptJero

9

Evet mümkün. Python 3.2.1'de aşağıdaki kodu yazdım:

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

Kullanım:

myfunction=overload(no_arg_func, one_arg_func, two_arg_func)

Unutmayın ki overloadişlevler tarafından döndürülen lambda , adlandırılmamış argümanların sayısına bağlı olarak çağrılacak işlevi seçer .

Çözüm mükemmel değil, ancak şu anda daha iyi bir şey yazamıyorum.


1

Doğrudan mümkün değil. Genelde hoş karşılanmasa da, verilen argümanlarda açık tür kontrolleri kullanabilirsiniz.

Python dinamiktir. Bir nesnenin ne yapabileceğinden emin değilseniz, şunu deneyin: ve bunun üzerinde bir yöntem çağırın, sonra hariç: hatalar.

Türlere göre aşırı yüklemeniz gerekmiyorsa, ancak yalnızca bağımsız değişken sayısına bağlı olarak, anahtar kelime bağımsız değişkenlerini kullanın.


3
İsteğe bağlı argümanları bildiğini sanmıyorum.
agf

0

aşırı yükleme yöntemleri python'da zordur. Bununla birlikte, dikteyi, listeyi veya ilkel değişkenleri aktarmanın kullanımı olabilir.

Kullanım durumlarım için bir şey denedim, bu, insanların yöntemleri aşırı yüklemelerine yardımcı olabilir.

Stackoverflow iş parçacığındaki örnek kullanımı ele alalım:

farklı sınıftan yöntemleri çağıran bir sınıf aşırı yükleme yöntemi.

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

uzak sınıftan bağımsız değişkenleri iletin:

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

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

Dolayısıyla, yöntem aşırı yüklemesinden liste, Sözlük veya ilkel değişkenler için işlem sağlanıyor.

kodlarınız için deneyin

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.