Python da Rastgele Sayıda İsimsiz Parametre Belirleme

Şimdiye kadar öğrendiğimiz pek çok fonksiyonun toplam kaç parametre alabileceği bellidir. Örneğin input() fonksiyonu yalnızca tek bir parametre alabilir. Eğer bu fonksiyona birden fazla parametre verirsek Python bize bir hata mesajı gösterecektir. Aynı şekilde mesela pow() fonksiyonunun da kaç parametre alabileceği bellidir. Ama örneğin print() fonksiyonuna verebileceğimiz parametre sayısı (teknik olarak 256 ile sınırlı olsa da) pratik olarak neredeyse sınırsızdır.

Peki acaba biz kendimiz, sınırsız parametre alabilen fonksiyonlar üretebilir miyiz?

Bu sorunun cevabı ‘evet’ olacaktır. Şimdi şu örneğe dikkatlice bakın:

def fonksiyon(*parametreler):
    print(parametreler)

fonksiyon(1, 2, 3, 4, 5)

Bu kodları çalıştırdığımızda şu çıktıyı alacağız:

(1, 2, 3, 4, 5)

Gördüğünüz gibi, fonksiyon tanımı içinde kullandığımız * işareti sayesinde fonksiyonumuzun pratik olarak sınırsız sayıda parametre kabul etmesini sağlayabiliyoruz. Bu arada, bu tür fonksiyonların alabileceği parametre sayısı, dediğimiz gibi, pratikte sınırsızdır, ama teknik olarak bu sayı 256 adedi geçemez.

Yukarıdaki kodların verdiği çıktının bir demet olduğuna dikkatinizi çekmek isterim. Bu bilgiye sahip olduktan sonra, bu tür fonksiyonları demet işleme kurallarına göre istediğiniz şekilde manipüle edebilirsiniz.

Peki böyle bir fonksiyon tanımlamak ne işimize yarar?

Mesela bu yapıyı kullanarak şöyle bir fonksiyon yazabilirsiniz:

def çarp(*sayılar):
    sonuç = 1
    for i in sayılar:
        sonuç *= i
    print(sonuç)

Bu fonksiyon kendisine verilen bütün parametreleri birbiriyle çarpar. Örneğin:

çarp(1, 2, 3, 4)

Bu kodun çıktısı 24 olacaktır. Gördüğünüz gibi, fonksiyonumuza istediğimiz sayıda parametre vererek bu sayıların birbiriyle çarpılmasını sağlayabiliyoruz.

Aslında burada kullandığımız * işareti size hiç yabancı değil. Hatırlarsanız print() fonksiyonundan bahsederken şuna benzer bir kullanım örneği vermiştik:

>>> print(*TBMM, sep='.')

T.B.M.M

Burada * işareti, eklendiği parametreyi öğelerine ayırıyor. sep parametresi ise * işaretinin birbirinden ayırdığı öğelerin arasına birer ‘.’ karakteri ekliyor.

Bu işaretin etkilerini şu örneklerde daha net görebilirsiniz:

>>> liste = ["Ahmet", "Mehmet", "Veli"]
>>> print(*liste)

Ahmet Mehmet Veli

>>> sözlük = {"a": 1, "b": 2}
>>> print(*sözlük)

a b

Gördüğünüz gibi, * işareti herhangi bir öğeyi alıp, bunu parçalarına ayırıyor. İşte bu * işaretini fonksiyon tanımlarken kullandığımızda ise bu işlemin tam tersi gerçekleşiyor. Yani fonksiyon tanımında parametrenin soluna * getirdiğimizde, bu fonksiyon çağrılırken verilen argümanlar tek bir değişken içinde bir demet olarak toplanıyor. Zaten bu konunun başında verdiğimiz şu örnekte de bu durum açıkça görünüyor:

def fonksiyon(*parametreler):
    print(parametreler)

fonksiyon(1, 2, 3, 4, 5)

Bu fonksiyonu çağırdığımızda şu çıktı veriliyor:

(1, 2, 3, 4, 5)

Aynen söylediğimiz gibi, fonksiyon() adlı fonksiyona argüman olarak verdiğimiz her bir öğenin (12345) tek bir demet içinde toplandığını görüyorsunuz.

Yıldızlı parametreler, tanımladığınız fonksiyonun parametre sayısını herhangi bir şekilde sınırlamak istemediğiniz durumlarda çok işinize yarar.

Elbette * işaretiyle birlikte kullanacağınız parametrenin adı olarak, Python’ın değişken adlandırma kurallarına uygun bütün kelimeleri belirleyebilirsiniz. Mesela biz yukarıda ‘parametreler’ adını tercih ettik. Ama Python dünyasında * işaretiyle birlikte kullanılacak parametrenin adı geleneksel olarak, ‘argümanlar’ anlamında ‘args’tır. Yani Python programcıları genellikle yukarıdaki gibi bir fonksiyonu şöyle tanımlar:

def fonksiyon(*args):
    ...

* işareti ile birlikte kullanılacak parametrenin adını ‘args’ yapmak bir zorunluluk olmamakla birlikte, başka Python programcılarının kodlarınızı daha kolay anlayabilmesi açısından bu geleneği devam ettirmenizi tavsiye ederim. Yazdığımız kodlarda Python programlama dilinin geleneklerine bağlı kalmak çoğunlukla iyi bir alışkanlıktır.

Alıntıdır.