Merhaba arkadaşlar.
Genellikle from
sözcüğünü, bir kütüphaneyi import
sözcüğü ile programa yüklerken kullanıyoruz. Ancak from
sözcüğünün kullanıldığı başka bir yer daha var. Bu başlıkta bundan bahsetmek isterim.
Diyelim aşağıdaki gibi bir fonksiyonumuz var. Bu aşağıdaki fonksiyon ne yapıyor bilmeyenler için anlatayım, izninizle.
def f(*args): pass
f(*args)
ifadesi, f
fonksiyonunun -255’e kadar- bir sürü argüman alabileceğini gösteriyor. Ana konudan sapmadan, isterseniz, 255 tane argüman alabileceğini nasıl öğrenebiliriz bulmaya çalışalım.
Yukarıdaki fonksiyona 255 tane argüman vererek çağırmaya çalışalım.
exec(f"f({', '.join(map(str, range(255)))})")
Bir de 256 tane argüman vererek çağırmaya çalışalım.
exec(f"f({', '.join(map(str, range(256)))})")
Şöyle bir hata almış olmamız lazım.
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<string>", line 1
SyntaxError: more than 255 arguments
Gördüğünüz gibi bir fonksiyona en fazla 255 tane argüman verilebiliyor.
Şimdi izninizle from
sözcüğünün farklı kullanımını sizlere anlatmaya çalışmak isterim.
Örneğin, aşağıdaki gibi bir fonksiyonumuz olsun.
def f(*args):
for i in args:
yield i
Yukarıdaki fonksiyonun ne yaptığını henüz bilmeyen arkadaşlar için kısaca bir açıklamada bulunayım.
Öncelikle yield
deyimi tıpkı return
gibi bir fonksiyondan değer döndürmeye yarar ancak burada bir değerden çok bir çok değer içeren bir üreteç elde edersiniz. Yukarıdaki fonksiyonda yield
yerine return
kullanılmış olsaydı, ilk i
değeri geri döndürülecekti, oysa yield
sözcüğü burada bütün i
’lere ulaşma imkanı tanıyor.
Şimdi basit bir tane dizi tanımlayalım.
dizi = ["elma", "armut", "çilek", "karpuz"]
dizi
’yi f(*args)
fonksiyonuna argüman olarak verelim. Ve aşağıdaki gibi ekrana yazdıralım.
print(*f(dizi))
Yukarıdaki print
fonksiyonunun ekrana bastıracağı çıktı aşağıdaki gibi olacaktır.
['elma', 'armut', 'çilek', 'karpuz']
f()
fonksiyonunun argümanı dizi
değil de *dizi
olsun bu sefer.
print(*f(*dizi))
Bu kez alacağımız çıktı aşağıdaki gibi olacaktır.
elma, armut, çilek, karpuz
Şimdi gelin yukarıdaki fonksiyonu biraz değiştirelim:
def f(*args):
yield from args
print(*f(dizi))
f
fonksiyonunun argümanına dizi
’yi yazalım ve bakalım nasıl bir sonuç elde ediyoruz.
['elma', 'armut', 'çilek', 'karpuz']
Gördüğünüz gibi bu fonksiyon da ilk f(dizi)
fonksiyonuna benzer bir çıktı verdi. f
fonksiyonuna argüman olarak bir de *dizi
’yi verelim.
print(*f(*dizi))
Şöyle bir çıktı almamız gerekir.
elma, armut, çilek, karpuz
Yine diğer fonkiyonun ürettiği sonuca benzer bir sonuç üretildi. Peki bu her zaman böyle mi olur? Gelin fonksiyonu biraz daha değiştirelim ve bu sorunun cevabını bulmaya çalışalım.
def f(*args):
for i in args:
yield i.upper() if isinstance(i, str) else i
Şimdi f(*args)
fonksiyonununa önce dizi
sonra *dizi
’yi argüman olarak verip, döndürdüğü değerleri ekrana yazdırmaya çalışalım…
print(*f(dizi))
Aşağıdaki gibi bir çıktı almamız gerekiyor:
['elma', 'armut', 'çilek', 'karpuz']
Argümanı *dizi
olduğunda nasıl bir çıktı veriyor ona bakalım.
print(*f(*dizi))
ELMA ARMUT ÇILEK KARPUZ
Yazdığımız i.upper() if isinstance(i, str) else i
deyimi sayesinde, tipi str
olan argüman büyük harflerle ekrana yazdırıldı.
Bu son f
fonksiyonumuzu from yield
deyimiyle birlikte tekrar yazalım.
def f(*args):
yield from args.upper() if isinstance(args, str) else args
Fonksiyona önce dizi
’yi argüman olarak verelim ve nasıl bir çıktı aldığımıza bakalım.
print(*f(dizi))
['elma', 'armut', 'çilek', 'karpuz']
Gördüğünüz gibi diğer fonksiyon ile benzer bir sonuç aldık. Peki argümana *dizi
’yi yazsak, o da benzer bir sonuç üretiyor mu bakalım.
print(*f(*dizi))
elma armut çilek karpuz
Bakın bu sefer farklı bir sonuç aldık. Yani ilk örnekte her iki argüman için de benzer sonuçlar almıştık ama bu örnekte son sonuç farklı çıktı. Acaba from yield
kullandığımız fonksiyonda nasıl bir değişiklik yapılmalı ki print(*f(*dizi))
fonksiyonu string değerlerini büyük harflerle ekrana bastırsın?
Şöyle yapabilirdik herhalde:
def f(*args):
yield from [i.upper() for i in args] \
if isinstance(args, tuple) else args
print(*f(*dizi))
Yukarıdaki kodları çalıştırdığımızda alacağımız çıktı şöyle olacaktır.
ELMA ARMUT ÇILEK KARPUZ
Peki, aynı fonksiyon print(*f(dizi))
şeklinde çağrılabilir miydi?
print(*f(dizi))
Bu kodları çalıştırdığımızda aşağıdaki gibi bir çıktı almamız gerekiyor:
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 2, in f
File "<stdin>", line 2, in <listcomp>
AttributeError: 'list' object has no attribute 'upper'
Peki, nasıl bir f
fonksiyonu yazılmalı ki, fonksiyonu print(*f(dizi))
şeklinde çağırdığımızda, bir önceki print(*f(*dizi))
fonksiyonunun ürettiği çıktı olan ELMA ARMUT ÇILEK KARPUZ
ile benzer olsun? Aşağıdakini bir deneyelim.
def f(*args):
yield from [i.upper() for i in args[0]] \
if isinstance(args, tuple) else arg
print(*f(dizi))
Bu kodları çalıştırdığımızda alacağımız çıktı aşağıdaki gibi olacaktır.
ELMA ARMUT ÇILEK KARPUZ
Son f
fonksiyonunun argümanı *dizi
şeklinde olursa alacağımız çıktı da şöyle olacaktır:
E L M A
Örneği bu kadar uzatmamın nedeni kafa karışıklığı yaratmak değildi, eğer bir kafa karışıklığına yol açtıysam şimdiden özür dilerim. Hatırlıyorsanız yukarıda şöyle bir şey yazmıştım:
İşte bu soruya cevap aramaya çalıştım ve gördüğüm kadarıyla,
def f(*args):
yield from args
ile
def f(*args):
for i in args:
yield args
ifadeleri benzer sonuçlar üretiyor üretmesine ancak yukarıdaki diğer fonksiyon örneklerini bu yapıya uydurarak çağırmaya çalıştığımızda farklı sonuçlar alabildiğimizi gördük ve benzer sonuçlar almak için fonksiyonları değiştirmek zorunda kaldık.
Bu konuyla alakalı söyleyebileceklerimin sonuna geldim. Okuduğunuz için teşekkür ederim.
Sevgiler, saygılar.