Şu ana kadar zengin Python kütüphaneleri sayesinde pek çok fonksiyonu kolayca kullandık. Öte yandan bazı durumlarda kendi fonksiyonlarımızı yazmak isteyebiliriz. Mesela Python'da kullanılan standart dize fonksiyonları Türkçe harfler ile başa çıkamıyorlar. Diyelim ki "ARMUT" dizesindeki büyük harfleri küçükleri ile değiştirmek istiyoruz. Bunun için dizeler için tanımlanmış olan **lower** fonksiyonunu kullanacağız.
In [145]:
meyva = "ARMUT"
print meyva.lower()
Buraya kadar bir terslik yok. Fakat aynı fonksiyon dizede Türkçe harfler varsa doğru çalışmıyor.
In [146]:
il = "IĞDIR"
print il.lower()
Bu sorunu herhangi bir dize içindeki harf gruplarını değiştirmek için kullanılan **replace** fonksiyonu ile çözebiliriz.
In [147]:
il = "IĞDIR"
il = il.replace("Ğ", "ğ")
il = il.replace("I", "ı")
print il.lower()
Peki ya kelimemiz "KEŞKÜL" olsa?
In [148]:
tat = "KEŞKÜL"
print tat.lower()
Belli ki "Ş" ve "Ü" harfleri için de harf değiştirme işlemlerini yapmamız gerekecek.
In [149]:
tat = "KEŞKÜL"
tat = tat.replace("Ş", "ş")
tat = tat.replace("Ü", "ü")
print tat.lower()
Bunun sonu yok. İyisi mi kelimeyi verdiğimizde Türkçe büyük harfleri küçükleri ile değiştiren bir fonksiyon yazmalı.
Python'da bir fonksiyonu **def** anahtar kelimesi ile tanımlıyoruz.
In [150]:
def lowertr(kelime):
kelime = kelime.replace("Ö", "ö")
kelime = kelime.replace("Ü", "ü")
kelime = kelime.replace("İ", "i")
kelime = kelime.replace("Ğ", "ğ")
kelime = kelime.replace("Ş", "ş")
kelime = kelime.replace("Ç", "ç")
kelime = kelime.replace("I", "ı")
kelime = kelime.lower()
print kelime
Fonksiyonumuzun ismi lowertr ve kelime isimli parametreyi alıyor. Hemen deneyelim.
In [151]:
lowertr("IĞDIR")
lowertr("KEŞKÜL")
İşte bu kadar. Şimdi küçük harflerle yazılmış olan kelimeyi de başka bir değişkene kaydetmeyi deneyelim.
In [152]:
dize = "IĞDIR KEŞKÜL CENNETİ"
dizekucuk = lowertr(tat)
print dizekucuk
İkinci satırdaki "None" kelimesi _dizgekucuk değişkeninin içinin boş olduğunu gösteriyor. Demek ki fonksiyonumuz küçük harflere çevirdiği dizgeyi geri döndürmüyor. Ufak bir değişiklik ile hemen hallederiz. Tek yapmamız gereken **return** anahtar kelimesi ile çağrılan fonksiyonun ne çevireceğini belirtmek.
In [153]:
def lowertr(kelime):
kelime = kelime.replace("Ö", "ö")
kelime = kelime.replace("Ü", "ü")
kelime = kelime.replace("İ", "i")
kelime = kelime.replace("Ğ", "ğ")
kelime = kelime.replace("Ş", "ş")
kelime = kelime.replace("Ç", "ç")
kelime = kelime.replace("I", "ı")
kelime = kelime.lower()
return kelime # Bu satır küçük harfli kelimeyi döndürüyor
Artık dizgekucuk değişkenine doğru şekilde atama yapabiliriz.
In [154]:
dizge = "IĞDIR KEŞKÜL CENNETİ"
dizgekucuk = lowertr(tat)
print dizge_kucuk
İşi biraz daha ilerletelim. İki seçeneğimiz olsun. İlk seçenekte daha önceki gibi dizeyi küçük harflere, ikinci seçenekte ise büyük harflere dönüştürelim. Seçeneği belirlemek için ikinci bir parametre tanımlayabiliriz. Bu parametre 1 değerini alırsa küçük harf seçeneğini, 0 değerini alırsa da büyük harf seçeneğini uygulayacağız.
In [161]:
def kucukbuyuk(kelime, secenek):
if (secenek):
kelime = lowertr(kelime) # Daha önce hazırlamıştık
else:
kelime = kelime.replace("ö", "Ö")
kelime = kelime.replace("ü", "Ü")
kelime = kelime.replace("i", "İ")
kelime = kelime.replace("ğ", "Ğ")
kelime = kelime.replace("ş", "Ş")
kelime = kelime.replace("ç", "Ç")
kelime = kelime.replace("ı", "I")
kelime = kelime.upper()
return kelime
Dikkat ederseniz daha önce tanımladığımız lowertr fonksiyonunu yeni fonksiyonumuzun ilk seçeneğinde kullandık.
In [162]:
print kucukbuyuk("Iğdır", 1)
print kucukbuyuk("Keşkül", 0)
Her seferinde 1 ya da 0 diye seçeneği girmek insanın canını sıkabilir. Özellikle de çoğu zaman küçük harflere dönüştürmeyi kullanacaksanız. Python'da bunun da çaresi var. Tek yapmamız gereken bazı parametrelerin varsayılan değerlerini girmek.
In [163]:
def kucukbuyuk(kelime, secenek=1):
if (secenek):
kelime = lowertr(kelime)
else:
kelime = kelime.replace("ö", "Ö")
kelime = kelime.replace("ü", "Ü")
kelime = kelime.replace("i", "İ")
kelime = kelime.replace("ğ", "Ğ")
kelime = kelime.replace("ş", "Ş")
kelime = kelime.replace("ç", "Ç")
kelime = kelime.replace("ı", "I")
kelime = kelime.upper()
return kelime
İkinci parametre, yani secenek, artık varsayılan parametre. Fonksiyon çağrılırken varsayılan parametrenin değeri verilmezse, fonksiyon içerisinde secenek parametresinin değeri 1 olarak alınıyor.
In [164]:
print kucukbuyuk("IĞDIR") # secenek parametresi varsayılan değeri alacak
print kucukbuyuk("kasımpatı", 0) # secenek parametresi ayrıca girilmiş
Burada bir noktaya dikkat etmeli. Varsayılan parametreler her zaman diğer parametrelerden sonra yazılmak zorundalar.
Parametrelerin varsayılan değerlerini girmenin getirdiği bir kolaylık daha var. Bu tür parametrelerden birkaç tane varsa, isimleri verilerek herhangi bir sırayla girilebiliyorlar. Bunun en güzel örneği grafik çizmede kullanılan **plot** fonksiyonu. Aşağıdaki örnekteki linewidth, color ve linestyle parametreleri x ve y parametrelerinden sonra istenilen sırada girilebilir.
In [165]:
% pylab inline
x = arange(0.0, 2.0, 0.01)
y = cos(2*pi*t)
plot(x, y, linewidth=2, color="red", linestyle="dashed")
Out[165]:
Basit birkaç sayısal örnek yapalım. Örneğin, bir dikdörtgenin iki kenarını parametre olarak alıp, alanını veren bir fonksiyon yazalım. İkinci kenar uzunluğunun varsayılan değeri 1 olsun.
In [4]:
def dikd_alan(en, boy=1):
return en*boy
In [5]:
print dikd_alan(3,5)
print dikd_alan(3)
print dikd_alan(boy=2, en=5)
Son örnekte, parametrelerin isimlerini kullandığımız için, fonksiyonda tanımlanmış sıralarını kullanmak zorunda kalmadık (yani önce en, sonra boy vermek zorunda değiliz).
Daha doğal bir varsayım olarak diyelim ki, sadece en verildiğinde boy'un da aynı değere sahip olmasını istiyoruz. Yani tek bir kenar ölçüsü verildiğinde dikdörtgenimizin kare olduğunu varsayıyoruz. Bunu yapmanın doğrudan bir yolu yok, ama şöyle bir numara yapabiliriz: boy için varsayılan değeri None olarak veririz, ve bu değer değiştirilmediyse en'e eşitleriz.
In [7]:
def dikd_alan(en, boy=None):
if boy == None:
boy = en
return en*boy
In [8]:
print dikd_alan(3,5)
print dikd_alan(3)
1'den başlayarak, verilen bir sayıya kadar tamsayıları toplayan bir fonksiyon:
In [32]:
def toplam(N):
t = 0
i = 1
while i<=N:
t += i
i += 1
return t
In [33]:
print toplam(100)
Bunu genelleştirelim; ilk'den N'ye kadar adim adımlarla ilerleyerek elde edilen aritmetik dizinin toplamını veren bir fonksiyon yazalım. Varsayılan değerler ilk için 0 ve adim için 1 olsun.
In [18]:
def toplam(N, ilk=0, adim=1):
t = 0
i = ilk
while i <= N:
t += i
i += adim
return t
In [ ]:
In [19]:
print toplam(100) # 0 + 1 + 2 + ... + 100
print toplam(100,10) # 10 + 11 + ... + 100
print toplam(100, adim=5) # 5 + 10 + ... + 100
Madem genelliyoruz, aritmetik dizilerin ötesine geçelim. Sözgelişi, genel bir f fonksiyonu için $\sum_{i=0}^{N} f(i)$ toplamını hesaplayacak bir fonksiyon yazalım.
Burada, toplam fonksiyonuna başka bir fonksiyonu parametre olarak vermeliyiz. Python'da her şey gibi fonksiyonlar da bir nesne olduğu için, bunu basit şekilde halledebiliriz.
In [20]:
def toplam(N, f):
t = 0
i = 0
while i<=N:
t += f(i)
i += 1
return t
Tabii bu toplamı yapabilmek için sayısal değer veren bir fonksiyon ismini kullanmalıyız. Sözgelişi, math modülünden karekök alma fonksiyonunu alalım.
In [21]:
from math import sqrt
print toplam(10, sqrt) # sqrt(0) + sqrt(1) + ... + sqrt(10)
Veya, kendimiz bir fonksiyon tanımlayalım.
In [22]:
def f(x):
return 1.0/(2*x+1)
print toplam(10, f) # 1/3 + 1/5 + ... + 1/21
Bu ve benzeri şekilde, bir fonksiyon nesnesi beklenen durumlarda başka bir alternatifimiz isimsiz fonksiyonlardır. Yukarıdaki örneği isimsiz fonksiyonlarla şöyle yazarız.
In [24]:
print toplam(10, lambda x: 1.0/(2*x+1))
Buradaki lambda, isimsiz fonksiyon yaratma komutudur. Ardından parametre listesi yazılır, iki nokta üstüste konur, ve geri verilecek değer yazılır. İstenirse, aşağıdaki gibi, isimlere atanıp tekrar kullanılabilirler de.
In [29]:
f = lambda x: x/(x+1.0)
g = lambda x,y: 1.0*(x+y)/(x*y)
print f(3)
print g(1,2)
İsimsiz fonksiyonlar, tek seferlik "kullan at" fonksiyon oluşturmaya yararlar. Hesaplamalı bilimde integral almak, kök bulmak, optimizasyon gibi, fonksiyonlar alarak işlemler yapan fonksiyonlarda kullanılabilirler.