İşlevler, bir dizi belirli eylemi gerçekleştirmek için organize, yeniden kullanılabilir ve modüler kod parçaları sağlar. İşlevler kodlama işlemini basitleştirir, gereksiz mantığı önler ve kodun izlenmesini kolaylaştırır. Bu yazıda, Python’daki işlevlerin oluşturulması ve kullanımına bakacağız.
Basit fonksiyon tanımlama ve fonksiyon çağırma
Python daha önce gördüğümüz print()
, input()
, len()
gibi birçok yerleşik fonksiyona sahiptir. Yerleşik işlevlerin yanı sıra, daha spesifik işler yapmak için kendi işlevlerinizi de oluşturabilirsiniz (bunlara kullanıcı tanımlı işlevler denir).
Sözdizimi
def function_name(arg1, … argN, *args, kw1, kw2=default, …, **kwargs)
:lambda arg1, … argN, *args, kw1, kw2=default, …, **kwargs
:
Python’da def
ifadesi
def
ifadesi python’da bir fonksiyonn tanımlamanın en yaygın yoludur. Bu ifade, tek cümleli bileşik bir ifadedir:
def fonksiyon_adi(parametere): ifade(ler)
fonksiyon_adi
işlev tanımlayıcısı olarak bilinir. İşlev tanımı yürütülebilir bir deyim olduğundan, işlev adı daha sonra çağrılabilecek işlev nesnesine bağlanır.
parametre
, işlev çağrıldığında bağımsız değişken olarak sağlanan değerleri gösteren isteğe bağlı bir listedir. Bir işlev, virgülle ayrılmış rasgele sayıda bağımsız değişkene sahip olabilir.
ifade(ler)
– işlev gövdesi olarak da bilinir – işlev her çağrıldığında yürütülen, boş olmayan, bir deyim dizisidir. Bu, herhangi bir girintili blok‘ta olduğu gibi, bir işlev gövdesinin boş olamayacağı anlamına gelir.
Fonksiyon tanımlama
Aşağıda, amacı her çağrıldığında Hello
yazdırmak olan basit bir fonksiyon tanımına bakalım:
def merhaba(): print("Hello")
Bu kadar basit. Fonksiyon tanımlarken def fonksiyon_adi():
ifadesini kullanıyoruz. Burada :
karakterine dikkat edin. Sonrasında alt satıra geçip girinti ekleyerek fonksiyon içerisinde yapmak istediğimiz işlevi yazıyoruz.
Fonksiyon çağırma
Şimdi tanımlanan fonksiyonu çağıralım: merhaba()
merhaba() # Çıktı: Hello
Aşağıda tek bir bağımsız değişkeni alan ve işlev her çağrıldığında verilen değeri görüntüleyen bir işlev tanımının başka bir örneğine bakalım:
def merhaba2(deger): print(deger)
merhaba2()
fonksiyonu bir bağımsız değişkenle çağrılmalıdır:
merhaba2("Howdy") # Çıktı: Howdy
Ayrıca bu bağımsız değişkene varsayılan bir değer de verebiliriz:
def merhaba2(deger="Howdy"): print(deger)
Böylece bir değer vermeden de işlevi çağırabilirsiniz:
merhaba() # Çıktı: Howdy
İşlevlerden değer döndürme
İşlevler doğrudan kullanabileceğiniz bir değer döndürebilir.
def beslik(): return 5 print(beslik()) # Döndürülen değeri yazdır # Çıktı: 5
veya daha sonra kullanmak üzere değeri kaydedebilirsiniz:
num = beslik() print(num) # Kaydedilen döndürülen değeri bastır # Çıktı: 5
veya herhangi bir işlem için döndürülen değer kullanılabilir:
print(beslik() + 10) # Çıktı: 15
İşlevde return
ile karşılaşılırsa, işlevden hemen çıkılır ve sonraki işlemler değerlendirilmez:
def beslik(): return 5 print('Bu satır bastırılmaz. Hiçbir zaman.') print(beslik()) # Çıktı: 5
Ayrıca birden fazla return
değeri de verebilirsiniz (bir demet şeklinde):
def iki_beslik(): return 5, 5 # iki tane 5 döndürür birinci, ikinci= iki_beslik() print(birinci) # Çıktı: 5 print(ikinci) # Çıktı: 5
return
ifadesi olmayan bir işlev örtülü olarak None
döndürür. Benzer şekilde, return
deyimi olan, ancak dönüş değeri veya değişken dönüşü olmayan bir işlev de None
döndürür.
Argüman ile fonksiyon tanımı
Argümanlar fonksiyon isminden sonra gelen parantez içerisinde tanımlanır.
def divide(dividend, divisor): # Fonksiyon ismi ve argümanları
# Argümanlara fonksiyon içerisinde isimleri ile ulaşılabilir.
print(dividend / divisor)
Fonksiyon adı ve argüman listesi işlevin imzası olarak adlandırılır. İsimlendirilmiş her argüman, işlevin yerel bir değişkenidir.
İşlev çağrılırken argümanlar sırayla işlev çağrısında verilir.
divide(10, 2)
# Çıktı: 5
Ya da, herhangi bir sırayla çağrılırken argüman isimleri kullanılır:
divide(divisor=2, dividend=10) # Çıktı: 5
Birden fazla argümanla işlev tanımlamak
Bir fonksiyon birçok argüman ile de tanımlanabilir. Buradaki tek kural; her argüman adının farklı olması ve isteğe bağlı argümanların isteğe bağlı olmayanlardan sonra olmasıdır:
def func(degisken1, degisken2, istege_bagli_degisken=10):
return '{0} {1} {2}'.format(degisken1, degisken2, istege_bagli_degisken)
İşlev çağrılırken anahtar kelimeler isimsiz olarak verilebilir. Ancak bu durumda sıralama önemli olur:
print(func(1, 'a', 100))
# Çıktı: 1 a 100
print(func('abc', 14))
# abc 14 10
Argümanlar isimli ve isimsiz olarak da verilebilir. Bu durumda ismi olanlar olmayanlardan sonra gelmelidir, ancak isimli olanların sırası önemli değildir:
print(func('Koddla ', optionalvalue='hoşgeldiniz', value2='Pythona '))
# Out: Koddla Pythona hoşgeldiniz
Yinelemeler ve sözlük açma
Fonksiyonlar pozisyona bağlı (positional), isme bağlı (named), değişken pozisyonuna bağlı (variable positional), anahtar kelime argümanı (Keyword args (kwargs)) türlerinde argüman tanımlanmasına izin verir. Aşağıda bu türlerin nasıl kullanılacağına dair örnekelere bakalım:
def unpacking(a, b, c=45, d=60, *args, **kwargs):
print(a, b, c, d, args, kwargs)
>>> unpacking(1, 2)
1 2 45 60 () {}
>>> unpacking(1, 2, 3, 4)
1 2 3 4 () {}
>>> unpacking(1, 2, c=3, d=4)
1 2 3 4 () {}
>>> unpacking(1, 2, d=4, c=3)
1 2 3 4 () {}
>>> pair = (3,)
>>> unpacking(1, 2, *pair, d=4)
1 2 3 4 () {}
>>> unpacking(1, 2, d=4, *pair)
1 2 3 4 () {}
>>> unpacking(1, 2, *pair, c=3)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: unpacking() got multiple values for argument 'c'
#c için birden fazla değer verildi
>>> unpacking(1, 2, c=3, *pair)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: unpacking() got multiple values for argument 'c'
#c için birden fazla değer verildi
>>> args_list = [3]
>>> unpacking(1, 2, *args_list, d=4)
1 2 3 4 () {}
>>> unpacking(1, 2, d=4, *args_list)
1 2 3 4 () {}
>>> unpacking(1, 2, c=3, *args_list)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: unpacking() got multiple values for argument 'c'
#c için birden fazla değer verildi
>>> unpacking(1, 2, *args_list, c=3)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: unpacking() got multiple values for argument 'c'
#c için birden fazla değer verildi
>>> pair = (3, 4)
>>> unpacking(1, 2, *pair)
1 2 3 4 () {}
>>> unpacking(1, 2, 3, 4, *pair)
1 2 3 4 (3, 4) {}
>>> unpacking(1, 2, d=4, *pair)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: unpacking() got multiple values for argument 'd'
#d için birden fazla değer verildi
>>> unpacking(1, 2, *pair, d=4)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: unpacking() got multiple values for argument 'd'
#d için birden fazla değer verildi
>>> args_list = [3, 4]
>>> unpacking(1, 2, *args_list)
1 2 3 4 () {}
>>> unpacking(1, 2, 3, 4, *args_list)
1 2 3 4 (3, 4) {}
>>> unpacking(1, 2, d=4, *args_list)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: unpacking() got multiple values for argument 'd'
#d için birden fazla değer verildi
>>> unpacking(1, 2, *args_list, d=4)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: unpacking() got multiple values for argument 'd'
#d için birden fazla değer verildi
>>> arg_dict = {'c':3, 'd':4}
>>> unpacking(1, 2, **arg_dict)
1 2 3 4 () {}
>>> arg_dict = {'d':4, 'c':3}
>>> unpacking(1, 2, **arg_dict)
1 2 3 4 () {}
>>> arg_dict = {'c':3, 'd':4, 'yeni_parametre': 75}
>>> unpacking(1, 2, **arg_dict)
1 2 3 4 () {'yeni_parametre': 75}
>>> unpacking(1, 2, *pair, **arg_dict)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: unpacking() got multiple values for argument 'd'
#d için birden fazla değer verildi
>>> unpacking(1, 2, 3, 4, **arg_dict)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: unpacking() got multiple values for argument 'd'
#d için birden fazla değer verildi
# Pozisyona bağlı argümanlar diğer türlere göre daha önceliklidir.
>>> unpacking(1, 2, **arg_dict, c=3)
1 2 3 4 () {'not_a_parameter': 75}
>>> unpacking(1, 2, 3, **arg_dict, c=3)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: unpacking() got multiple values for argument 'c'
#c için birden fazla değer verildi
Açıklamalar
İşlevlerle yapabileceğiniz 5 temel şey:
Değişkenlere işlevler atayın:
def f(): print(20) y = f y() # Çıktı: 20
Fonksiyonlar içinde fonksiyonlar tanımlayın:
def f(a, b, y): def inner_add(a, b): # inner_add f dışındaki diğer kod parçalarından gizlidir return a + b return inner_add(a, b)**y
İşlevler diğer işlevleri döndürebilir
def f(y): def nth_power(x): return x ** y return nth_power # işlev döndürür sayinin_karesi = f(2) # sayının karesini döndüren fonksiyon sayinin_kupu = f(3) # sayının küpünü döndüren fonksiyon sayinin_karesi(3) # Çıktı: 9 sayinin_kubu(2) # Çıktı: 8
İşlevler diğer işlevlere parametre olarak geçirilebilir:
def a(x, y): print(x, y) def b(fun, str): # b iki argümana sahip: bir fonksiyon ve bir dize fun('Hello', str) b(a, 'Sophia') # Çıktı: Hello Sophia
İç işlevlerin kendisini çevreleyen koda erişimi vardır
def dis_fonksiyon(name): def ic_fonksiyon(): # name değişkeni iç fonksiyonda da görülür return "Hello "+ name + "!" return ic_fonksiyon greet = dis_fonksiyon("Sophia") print(greet()) # Çıktı: Hello Sophia!
Fonksiyonda return ifadesi
Diğer birçok dilden farklı olarak, işlevin dönüş türünü açıkça bildirmeniz gerekmediğini fark etmişsinizdir. Python işlevleri, return
anahtar kelimesi aracılığıyla herhangi bir türdeki değerleri döndürebilir. Bir fonksiyon herhangi bir türde sonuç döndürebilir:
def farkli_turler(x): if x < 0: return "Hello!" else: return 0 print(farkli_turler(1)) print(farkli_turler(-1)) # Çıktı: 0 Hello!
Bu kod çağırıldığında doğru bir şekilde işlendiği sürece tamamen geçerli bir Python kodudur.
return deyimi olmadan yürütmenin sonuna ulaşan bir işlev her zaman şunu döndürür: None
Python’da pass ifadesi
def hicbir_sey_yapma(): pass print(hicbir_sey_yapma()) # Çıktı: None
Daha önce de belirtildiği gibi, bir işlev tanımı, bir işlev gövdesine, boş olmayan bir deyimler dizisine sahip olmalıdır. Bu nedenle pass
ifadesi, null bir işlem olan işlev gövdesi olarak kullanılır – yürütüldüğü zaman hiçbir şey olmaz. Bu ifade, adı üzerinde, sadece atlar. Bir deyim sözdizimsel olarak gerekli olduğunda, ancak hiçbir kodun yürütülmesi gerekmediğinde yer tutucu olarak kullanışlıdır.
Bir işlevi rasgele sayıda bağımsız değişkenle tanımlama
Konumsal argümanlar:
Rasgele sayıda bağımsız değişken alabilen bir fonksiyonun tanımlanması için bağımsız değişkenlerden birinin önüne *
getirilir
def func(*args): # args verilen tüm parametreleri içeren bir tuple olacaktır for i in args: print(i) func(1, 2, 3) # 3 argüman ile çağrı # Çıktı: 1 # 2 # 3 arg_list = [1, 2, 3] func(*arg_list) # Liste değerleri ile çağrı, * listeyi açar # Çıktı: 1 # 2 # 3 func() # argümansız çağrı # Çıktı yok
args
için varsayılan bir değer sağlayamazsınız. Örneğin, func(*args=[1, 2, 3])
ifadesi bir sözdizimi hatası oluşturacaktır (hatta derlemez bile).
İşlevi çağırırken args için isim sağlayamazsınız, örneğin func(*args=[1, 2, 3])
bir TypeError
oluşturur.
Ancak, bağımsız değişkenleriniz zaten bir dizide (veya başka bir döndürülebilir veri türünde) ise, işlevinizi şu şekilde çağırabilirsiniz: func(*degerlerim)
Bu bağımsız değişkenlere (*args
) index ile erişilebilir. Örneğin ilk bağımsız değişkeni args[0]
ile çağırırız.
Anahtar bağımsız değişkenler
Fonksiyon tanımında iki tane *
içeren argüman oluşturarak istediğiniz sayıda bağımsız değişken alabilirsiniz:
def func(**kwargs): # kwargs anahtar ve değer çiftlerini içeren bir sözlük olacaktır for name, value in kwargs.items(): print(name, value) func(value1=1, value2=2, value3=3) # 3 argüman # Çıktı: value1 1 # value2 2 # value3 3 func() # argümansız # Çıktı yok my_dict = {'foo': 1, 'bar': 2} func(**my_dict) # bir sözlük ile çağrı # Çıktı: foo 1 # bar 2
Bu argümanları isimleri olmadan sağlayamazsınız, örneğin func(1, 2, 3)
bir TypeError
oluşturur.
kwargs
basit bir yerel python sözlüğüdür. Örneğin args['value1']
, value1
bağımsız değişkeninin değerini verecektir. Tabiki böyle bir argüman olup olmadığını kontrol etmeniz gerekir. Aksi takdirde bir KeyError
hatası oluşacaktır.
Uyarı – Konumasal/anahtar kelimelerin pozisyonu
*args ve **kwargs’ı diğer isteğe bağlı ve gerekli argümanlarla da kullanabilirsiniz, ancak tanımın içindeki sıra önemlidir.
Konumsal/anahtar kelime bağımsız değişkenleri önce gelir (Gerekli bağımsız değişkenler).
Sonra keyfi argümanlar gelir: *arg
(İsteğe bağlı)
Ardından, anahtar kelime argümanları gelir. (Gerekli).
Sonra keyfi anahtar kelime argümanları gelir. **kwargs
(İsteğe bağlı)
# |-konumsal-|-isteğe bağlı-|---anahtar-kelime--|-isteğe bağlı-| def func(arg1, arg2=10 , *args, kwarg1, kwarg2=2, **kwargs): pass
arg1
verilmelidir, aksi takdirde birTypeError
oluşturulur.arg1
konumsal (func(10)
) veya anahtar kelime argümanı (func(arg1=10)
) olarak verilebilir.kwarg1
ayrıca verilmelidir, ancak yalnızca anahtar kelime-değer olarak sağlanabilir:func(kwarg1=10)
arg2
vekwarg2
isteğe bağlıdır. Verilen değer değiştirilecekse,arg1
(konumsal veya anahtar kelime) vekwarg1
(yalnızca anahtar kelime) için aynı kurallar uygulanır.*args
ek konumsal parametreleri yakalar. Ancak,arg1
vearg2
argümanlarının daha önce sağlanması gerektiğini unutmayın:func(1, 1, 1, 1)
**kwargs
tüm ek anahtar kelime parametrelerini yakalar.- Python 3’te, sonraki tüm bağımsız değişkenlerin anahtar sözcük olarak belirtilmesi gerektiğini belirtmek için tek başına * kullanabilirsiniz. Örneğin,
math.isclose
işlevi Python 3.5 ve sonraki sürümlerindedef math.isclose (a, b, *, rel_tol=1e-09, abs_tol=0.0)
ile tanımlanır; bu, ilk iki bağımsız değişkenin konumsal olarak sağlanabileceği, ancak isteğe bağlı üçüncü ve dördüncü parametrelerin yalnızca anahtar kelime bağımsız değişkenleri olarak sağlanabileceği anlamına gelir.
Python 2.x anahtar sözcük parametrelerini desteklemez. Bu davranışa kwargs
ile öykünülebilir:
def func(arg1, arg2=10, **kwargs): try: kwarg1 = kwargs.pop("kwarg1") except KeyError: raise TypeError("missing required keyword-only argument: 'kwarg1'") kwarg2 = kwargs.pop("kwarg2", 2) # function body ...
Adlandırma hakkında not
İsteğe bağlı konumsal argümanların args
ve isteğe bağlı anahtar kelime argümanlarının kwargs
olarak isimlendirilmesi bir kural olmamakla birlikte geleneksel olarak kullanılan isimlerdir. İstediğiniz herhangi bir adı kullanabilirsiniz. Ancak başkalarının ne yaptığınızı bilmesi için bu geleneği sizin de takip etmeniz yararlı olacaktır – hatta daha sonra kendiniz için bile yararlı olur.
Benzersizlik Hakkında Not
Herhangi bir fonksiyon sıfır veya bir *args
ve sıfır veya bir **kwargs
ile tanımlanabilir ancak her birinden birden fazla verilerek tanımlanamaz. Ayrıca, *args
son konumsal bağımsız değişken olmalı ve **kwargs
son parametre olmalıdır. Her ikisinden birden fazlasını kullanmaya çalışmak bir Sözdizimi Hatası özel durumuna neden olur.
İsteğe bağlı değişkenlerle işlev tanımlama
İsteğe bağlı bağımsız değişkenler, bağımsız değişken adına varsayılan bir değer atayarak (kullanılarak) tanımlanabilir:
def make(action='nothing'): return action
Bu işlev 3 farklı şekilde çağrılabilir:
make("fun") # Çıktı: fun make(action="sleep") # Çıktı: sleep # Parametre isteğe bağlı olduğu için verilmediğinde varsayılan değeri ile işlev çağırılır make() # Çıktı: nothing
Not: Değiştirilebilir türler (list
, dict
, set
, vb.) varsayılan özellik olarak verildiğinde dikkat edilmelidir. Varsayılan argümanın herhangi bir şekilde değiştirilmesi onu kalıcı olarak değiştirecektir.
İsteğe bağlı değiştirilebilir değişkenlerle işlev tanımlama
İsteğe bağlı bağımsız değişkenleri değiştirilebilir bir varsayılan türle kullanırken beklenmeyen davranışlar oluşabilir.
Sorun
Bu sorun, işlev değişkenlerinin, işlev çağrıldığında (diğer birçok dil gibi) oluşturulması yerine işlevin tanımlandığı noktada oluşturulması sebebiyle ortaya çıkar. Varsayılan değerler, işlev nesnesinin __defaults__
değişkeninin içinde depolanır.
def f(a, b=42, c=[]): pass print(f.__defaults__) # Çıktı: (42, [])
Değişmez türler için bu bir sorun değildir, çünkü değişkeni mutasyona uğratmanın bir yolu yoktur; ancak, orijinal değerler değiştirilmeden yeniden atanabilir. Bu nedenle, sonraki sürümlerin aynı varsayılan değere sahip olması garanti edilir. Ancak, değiştirilebilir bir tür için, özgün değer, çeşitli üye işlevlerine çağrılar yaparak mutasyona uğrayabilir. Bu nedenle, işleve yapılan ardışık çağrıların ilk varsayılan değere sahip olacağı garanti edilmez.
def append(elem, to=[]): to.append(elem) # varsayılan to değişkenine append() uygulanması varsayılan değeri değiştirir return to append(1) # Çıktı: [1] append(2) # Listeye yeni bir öğe atar # Çıktı: [1, 2] append(3, []) # Yeni bir liste oluşturmak beklenmedik bir sonuç doğurur # Çıktı: [3] # İşlevin tekrar çağırılması ilk listeye ekleme yapar append(4) # Out: [1, 2, 4]
Not: PyCharm gibi bazı IDE’ler, değiştirilebilir bir tür varsayılan öznitelik olarak belirtildiğinde bir uyarı verir.
Çözüm
Varsayılan değişkenin her zaman işlev tanımında belirttiğiniz değişken olduğundan emin olmak istiyorsanız, çözüm varsayılan değişkeninizi her zaman değişmez bir tür ile kullanmaktır.
Varsayılan olarak değiştirilebilir bir türe ihtiyaç duyulduğunda bunu başarmak için yaygın bir deyim, varsayılan değişken olarak None
(değişmez) kullanmak ve ardından varsayılan değişken istenilen değere eşit olduğunda varsayılan değere bunu atamaktır.
def append(elem, to=None): if to is None: to = [] to.append(elem) return to
Argüman geçişi ve değişkenlik
İlk olarak biraz terminoloji:
- bağımsız değişken – argüman (gerçek parametre): bir işleve geçirilen gerçek değişken;
- parametre (formal parametre): bir işlevde kullanılan alıcı değişken.
Python’da, bağımsız değişkenler atama ile geçirilir (bağımsız değişkenlerin değer/referans/işaretçi ile geçirilebildiği diğer dillerin aksine).
Bir parametrenin değiştirilmesi bağımsız değişkeni değiştirir (bağımsız değişkenin türü değiştirilebilirse):
def foo(x): # x parametre x[0] = 9 # Bu satır x ve y ile isimlendirilmiş listeleri değiştirir print(x) y = [4, 5, 6] foo(y) # foo işlevini y argümanı ile çağıralım # Çıktı: [9, 5, 6] # x ile isimlendirilen liste değişti print(y) # Çıktı: [9, 5, 6] # x ile isimlendirilen liste de değişti
Parametrenin yeniden atanması, bağımsız değişkeni yeniden atamaz:
def foo(x): # x parametre, foo(y) çağırıldığında y'yi x'e atarız x[0] = 9 # Bu x ve y ile isimlendirilmiş listeleri değiştirir x = [1, 2, 3] # x şimdi başka bir listeyi tanımlıyor (y etkilenmiyor) x[2] = 8 # Bu satır x'i değiştirirken y'yi değiştirmez y = [4, 5, 6] # y arguman, x parameter foo(y) # "x = y" yazmışız gibi düşünün ve 1. satıra gidin y # Çıktı: [9, 5, 6]
Python’da, değişkenlere gerçekten değer atamıyoruz, bunun yerine değişkenleri (ad olarak kabul edilen) nesnelere bağlarız (yani atarız, ekleriz).
- Değiştirilemeyenler: Tamsayılar, dizeler, demetler vb. Tüm işlemler birer kopya oluşturur.
- Değiştirilebilirler: Listeler, sözlükler, setler vb. İşlemler mutasyona uğrayabilir veya uğramayabilir.
x = [3, 1, 9] y = x x.append(5) # x ve y listelerinin ikisini de değiştirir, x ve y'nin ikisi de[3, 1, 9]'e bağlı x.sort() # x ve y listelerinin ikisini de değiştirir (yerinde sıralama) x = x + [4] # Listeleri değiştirmez (sadece x'in kopyasını oluşturur, y'yi değil) z = x # z, x'e eşit ([1, 3, 9, 4]) x += [6] # x ve z listelerinin ikisini de değiştirir x = sorted(x) # Listeyi değiştirmez (sadece x'in kopyasını oluşturur). x # Çıktı: [1, 3, 4, 5, 6, 9] y # Çıktı: [1, 3, 5, 9] z # Çıktı: [1, 3, 5, 9, 4, 6]
İsimlendirilmiş parametre kullanmaya zorlama
Fonksiyon tanımındaki ilk yıldız * sonrasında verilen tüm parametreler anahtar gerektirir.
def f(*a, b):
pass
f(1, 2, 3)
# TypeError: f() missing 1 required keyword-only argument: 'b'
# anahtar gerektiren parametre verilmedi
Python3’te fonksiyon tanımına sadece yıldız ekleyerek sonraki parametrelerin hepsinin anahtar gerektirdiği belirtilebilir
def f(a, b, *, c):
pass
f(1, 2, 3)
# TypeError: f() takes 2 positional arguments but 3 were given
f(1, 2, c=3)
# Hata yok
Özyinelemeli Fonksiyonlar
Özyinelemeli işlelvler kendi tanımında yine kendisini çağıran işlevlerdir. Örneğin, matematiksel fonksiyon olan faktöriyel için tanımlanan fonksiyon aşağıdaki gibi olabilir: (n) = n * (n-1) * (n-2) *… * 3 * 2 * 1
def factorial(n):
#n integer olmalı
if n == 0:
return 1
else:
return n*factorial(n-1)
Beklendiği gibi çıktı:
factorial(0)
#Çıktı 1
factorial(1)
#Çıktı 1
factorial(2)
#Çıktı 2
factorial(3)
#Çıktı 6
Bu fonksiyonun tanımında kendini çağıran bir fonksiyon olduğunu unutmayın. Fonksiyon sona ulaştığında return n*factorial(n-1)
nedeniyle kendini tekrar çağırır.
Bazı özyinelemeli işlevler lambda kullanılarak da uygulanabilir:
factorial = lambda n: 1 if n == 0 else n*factorial(n-1)
Bu programın çıktısı da yukarıdaki ile aynı olacaktır.
Özyineleme Limiti
Python uygulamasına bağlı olarak özyinelenme derinliğinde sınır bulunur. Sınıra ulaşıldığında, RuntimeError istisnası yükseltilir:
def yinele(derinlik):
try:
cursing(derinlik+ 1) # aslında, tekrar-yinele
except RuntimeError as RE:
print('{} kere yinelendi!'.format(derinlik))
yinele(0)
# Çıktı: 1083 kere yinelendi!
Özyineleme derinliğini sys.setrecursionlimit(limit)
ile değiştirmek mümkündür. Şuanki limitin kaç olduğu ise sys.getrecursionlimit()
ile görülebilir.
sys.setrecursionlimit(2000)
yinele(0)
# Out: 1997 kere yinelendi!
Python 3.5’ten itibaren, yükseltilen istisna RecursionError
olmuştur. Bu istisna da RuntimeError
‘ın bir türevidir.
İç içe fonksiyonlar
Pythondaki fonksiyonlar birinci dereceden nesnelerdir. Dolayısıyla herhangi bir kapsamda tanımlanabilirler:
def fibonacci(n):
def step(a,b):
return b, a+b
a, b = 0, 1
for i in range(n):
a, b = step(a, b)
return a
Fonksiyonlar herhangi bir nesne türü gibi atanabilirler veya parametre olarak verilebilirler:
def make_adder(n):
def adder(x):
return n + x
return adder
add5 = make_adder(5)
add6 = make_adder(6)
add5(10)
#Çıktı: 15
add6(10)
#Çıktı: 16
def repeatedly_apply(func, n, x):
for i in range(n):
x = func(x)
return x
repeatedly_apply(add5, 5, 1)
#Çıktı: 26
Python’da fonksiyon örnekleri
Verilen sayıları toplama fonksiyonu
Aşağıdaki sum fonksiyonu liste ile verilen sayıları toplar ve toplamı yazdırır:
def sum(values): # values 'list' türünde
result = 0
for value in values:
result += value
print(result)
Kelime içerisindeki harfleri sayma
count_letters fonksiyonu argüman olarak verilen kelimedeki harfleri sayar ve döndürür:
def count_letters(word):
return count_vowels(word) + count_consonants(word)