5. Demetler (Tuples)¶
Bu bölümde “tuple” diye bir şeyden söz edeceğiz. Biz buna Türkçe’de genellikle “demet” adını veriyoruz. Demetler de tıpkı listeler, sayılar ve karakter dizileri gibi, Python’daki veri tiplerinden biridir. Demetler bazı yönleriyle listelere benzerler, ama listelerle aralarında çok önemli bir fark vardır. Listeler “değiştirilebilir” (mutable) bir veri tipiyken, demetler ise “değiştirilemez” (immutable) bir veri tipidir. Peki bu ne anlama geliyor? Hatırlarsanız listeler konusunu incelerken listelerin bazı metotları olduğundan söz etmiştik. Örneğin remove() metodu bunlardan biriydi. Mesela bu metodu kullanarak şöyle bir şey yapabiliyorduk:
>>> geliştirme_araçları = ["Drpython", "Spe", "IDLE", "Komodo", "Eclipse"]
>>> geliştirme_araçları.remove("IDLE")
>>> print(geliştirme_araçları)
['Drpython', 'Spe', 'Komodo', 'Eclipse']
Gördüğünüz gibi remove() metodunu kullanarak, “geliştirme_araçları” adlı liste üzerinde değişiklik yapabildik. Mesela şu yöntemi kullanarak, liste öğelerinden birini silip yerine başka bir öğe de koyabiliriz:
>>> geliştirme_araçları[1] = "Kwrite"
>>> print(geliştirme_araçları)
['Drpython', 'Kwrite', 'Komodo', 'Eclipse']
Burada en son komutun çıktısına baktığımızda, listenin birinci sırasındaki “Spe” adlı öğenin yerine “Kwrite” öğesinin geldiğini görüyoruz. Bu durum, yani listeler üzerinde değişiklik yapabilme olanağı, listelerin “değiştirilebilir” bir veri tipi olmasından kaynaklanıyor. Mesela aynı şeyi karakter dizileri ile yapamayız:
>>> a = "Adana"
>>> a[3] = "m"
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: 'str' object does not support item assignment
Gördüğünüz gibi, böyle bir şey yapmaya çalıştığımızda Python bize bir hata mesajı gösteriyor. Çünkü karakter dizileri, listelerin aksine değiştirilebilme kabiliyetine sahip değildir. Yani bunlar “değiştirilemeyen” (immutable) veri tipleridir. Elbette karakter dizileri üzerinde de değişiklik yapmanın yolları var. Biz “Karakter Dizileri” konusunu ayrıntılı olarak incelediğimiz zaman bütün bu özellikleri tek tek öğreneceğiz. Şimdilik konumuzdan sapmayalım...
Tıpkı karakter dizileri gibi, demetler de değiştirilemeyen veri tipleridir. Demetlere kısaca değindiğimize göre, gelin isterseniz bu “giriş” bölümünü burada sonlandırıp asıl konumuza geçelim...
5.1. Demetleri Tanımlamak¶
Bir önceki bölümde demetler konusuna kısaca bir giriş yapmıştık. O bölümde, demetlerin listelere benzediğini ifade etmiştik. Hatırlarsanız listeleri şöyle tanımlıyorduk:
>>> liste = []
Burada boş bir liste tanımladık. Demetler de buna benzer bir şekilde tanımlanır:
>>> demet = ()
Gördüğünüz gibi, listelerdeki köşeli parantezlerin yerini demetlerde normal parantezler alıyor... İsterseniz yukarıda tanımladığımız veri tiplerinin sağlamasını yapalım:
>>> type(liste)
<class 'list'>
Demek ki tanımladığımız şey gerçekten de bir listeymiş... Bir de şuna bakalım:
>>> type(demet)
<class 'tuple'>
Burada gördüğümüz “tuple” ifadesi Türkçe’de “demet” anlamına geliyor. Demek ki burada oluşturduğumuz veri tipi gerçekten de bir demetmiş...
Daha önce “dir(list)” komutunu kullanarak, listelerin metotlarını sıralamayı öğrenmiştik. Şimdi de demetlerin metotlarına bakalım:
>>> dir(tuple)
['__add__', '__class__', '__contains__', '__delattr__', '__doc__',
'__eq__', '__format__', '__ge__', '__getattribute__', '__getitem__',
'__getnewargs__', '__gt__', '__hash__', '__init__', '__iter__',
'__le__', '__len__', '__lt__', '__mul__', '__ne__', '__new__',
'__reduce__', '__reduce_ex__', '__repr__', '__rmul__', '__setattr__'
, '__sizeof__', '__str__', '__subclasshook__', 'count', 'index']
Daha önce listelerin metotlarını almak için kullandığımız “list” yerine burada “tuple” kelimesini yazdığımıza dikkat edin. Elbette dir() metodunu şu şekilde kullanabileceğimizi de tahmin ediyorsunuzdur:
>>> dir(demet)
Burada daha önce tanımladığımız “demet” adlı öğeden yararlandık. Hatta istersek şöyle bir şey bile yazabiliriz:
>>> dir(())
Burada ise, demetlerin ayırt edici özelliği olan parantezleri kullandık. Benzer bir şeyi listeler için yapmak isteseydik şöyle bir yazım tarzı benimseyecektik:
>>> dir([])
Burada da listelerin ayırt edici özelliği olan köşeli parantezlerden faydalandık...
dir(tuple) komutundan elde ettiğimiz çıktılar arasında, içinde “__” işareti olmayanlar bizim ilgi alanımıza giren metotlar oluyor. Tıpkı daha önce listeler için yaptığımız gibi burada da ufak bir-iki satırlık kod yardımıyla dir(tuple) çıktısı içinde bizim ilgimizi çeken metotları alabiliriz:
>>> for i in dir(tuple):
... if "_" not in i:
... print(i)
...
count
index
Demek ki demetlerin yalnızca iki adet metodu varmış. Demetlerin metot sayısı listelere kıyasla epey az. Bunun nedeni, daha önce bahsettiğimiz “değiştirilebilme/değiştirilememe” meselesidir... Demetler, listelerin aksine değiştirilemeyen veri tipleri olduğu için, doğal olarak, değişiklik yapmaya yönelik metotlara sahip değildir. Listeler ise değiştirilebilen veritipleri olduğu için, append(), extend() ve remove() gibi, liste üzerinde değişiklik yapmayı sağlayan metotlar barındırır. Zaten dikkat ederseniz, demetlerin sahip olduğu bu iki metot da değişiklik yapmaya değil, bir demetin öğeleri hakkında bilgi vermeye yöneliktir. dir(tuple) komutundan elde ettiğimiz çıktıda görünen index() ve count() metotlarının ne işe yaradığını az çok tahmin edersiniz. Bunları zaten listeleri işlerken de görmüştük. Burada da işlevleri aynıdır.
Peki demetler ne işe yarar? Yani listeler gibi oldukça güçlü bir veri tipi önümüzde dururken demetleri kim takar!.. Elbette Python geliştiricileri çeşit olsun diye yerleştirmemişler demet diye bir şeyi dilin içine... Demetlerin de gerekli olduğu yerler vardır.
Bir defa demetler listelere kıyasla daha hızlı çalışırlar. Dolayısıyla üzerinde değişiklik yapmanız gerekmeyecek öğeleri gruplarken listeler yerine demetleri kullanmayı tercih edebilirsiniz. Ayrıca demetler değiştirilemeyen bir veri tipi olduğu için, bu veri tipini, program boyunca değişmesini istemediğimiz öğeleri gruplamak için de kullanabiliriz. Yani bir bakıma “salt-okunur” öğeleri demetler içinde saklamayı tercih edebiliriz...
Örnek olması açısından bir demet tanımlayalım:
>>> personel = ("Mehmet", "Ahmet", "Zeliha")
Böylelikle üç öğeli bir demet tanımlamış olduk. Listelerle yapabildiğimiz bazı şeyleri demetlerle de yapabiliriz. Mesela:
>>> personel[0]
'Mehmet'
>>> personel[:-1]
('Mehmet', 'Ahmet')
>>> personel[::-1]
('Zeliha', 'Ahmet', 'Mehmet')
Ama tabii ki şöyle bir şey mümkün değildir:
>>> personel[1] = "İlkay"
Neden? Çünkü, daha önce de birkaç kez söylediğimiz gibi, demetler üzerinde değişiklik yapamayız. Demetler “değiştirilemeyen” (immutable) veri tipleridir.
Demetlerin ilginç bir özelliği daha vardır. Her ne kadar demetlerin ayırt edici özelliği “()” işareti olsa da demetleri tanımlamak için parantez kullanmak zorunda değiliz:
>>> a = "Ahmet", "Mehmet", "Zarife"
Hemen bu “a” değişkeninin tipini kontrol edelim:
>>> type(a)
<class 'tuple'>
Gördüğünüz gibi, parantezleri kullanmadan da demet tanımlayabiliyoruz. Bu demek oluyor ki, aslında bir değişkene birden fazla değer atadığımızda yaptığımız şey bir demet tanımlamak. Tek öğeli bir değişken, içinde sakladığı verinin tipiyle anılır. Yani:
>>> hava = "yağmurlu"
>>> type(hava)
<class 'str'>
Bir de şuna bakalım:
>>> hava = 10
>>> type(hava)
<class 'int'>
...ama birden fazla öğe barındıran değişkenler tip olarak birer demettir...
Mesela:
>>> hava = "yağmurlu", "bulutlu", "rüzgârlı"
>>> type(hava)
<class 'tuple'>
Ya da:
>>> hava = 10, 15, 17
>>> type(hava)
<class 'tuple'>
Elbette, eğer istersek yukarıdaki demetlerin öğelerini parantez içinde de belirtiriz. Bu şekilde hangi tür bir veri tipi tanımladığımızı daha açık ve net bir şekilde belli etmiş oluruz.
5.2. Tek Öğeli bir Demet Tanımlamak¶
Bir önceki bölümde bir demetin nasıl tanımlanacağını gördük. Yalnız tanımladığımız demetler hep birden fazla öğe içeriyordu. Önceki bölümde tek öğeli bir demetin nasıl tanımlanacağını öğrenmedik. “Tek bir öğe yazarsın, olur sana tek öğeli bir demet!” dediğinizi duyar gibiyim... Ama ne yazık ki durum bu kadar basit değil. Hemen durumun karmaşıklığını gösteren bir örnek yaparak işe başlayalım:
>>> a = ("tek")
>>> type(a)
<class 'str'>
Gördüğünüz gibi hüsrana uğradık!... Basitçe tek bir öğe içeren bir demet tanımlamaya çalışırken, elde ettiğimiz şey bir “str”, yani “karakter dizisi” oldu... Demek ki tek bir öğeyi parantez içine almak yeterli olmuyormuş... Peki ne yapacağız? Elbette elimiz kolumuz bağlı oturmayacağız. Bu tür durumlar için Python’un özel bir çözümü vardır. Görelim:
>>> a = ("tek",)
>>> type(a)
<class 'tuple'>
Gördüğünüz gibi, “tek” adlı öğenin yanına minik bir virgül işareti koyarak amacımıza ulaşabildik... İşte Python’da tek öğeli bir demet tanımlamanın yolu budur. Gözünüze tuhaf görünmüş olabilir, ama zamanla alışırsınız...
“a” adlı demeti parantezsiz olarak kullanmak istersek de buna benzer bir yol izlememiz gerekir:
>>> a = "tek",
>>> type(a)
<class 'tuple'>
Çünkü eğer oraya o virgülü koymazsak elde edeceğimiz şey bir karakter dizisi olacaktır...
Önceki bölümlerde demetler hakkında şöyle bir şey demiştik: “Demetler değiştirilemeyen bir veri tipidir.” Gerçekten de öyledir... Ama değiştirilemeyen bir veri tipi olan demetler, öğe olarak, değiştirilebilen veri tiplerini barındırabilir. Yani mesela şöyle bir şey yapabiliriz:
>>> a = (["elma", "armut", "erik"], 1, 2, 3)
Gördüğünüz gibi, “a” adlı demetimizin sıfırıncı öğesi bir liste. Buna şu şekilde erişebiliriz:
>>> a[0]
Eğer bu listenin ilk öğesine erişmek istersek ne yapmamız gerektiğini biliyorsunuz:
>>> a[0][0]
Demetimizin sıfırıncı öğesi bir liste olduğu için, listelerin sahip olduğu bütün özellikleri taşır. Yani listelerin metotlarını burada kullanabiliriz:
>>> a[0].append("kestane")
Eğer tek bir öğe içeren ve bu tek öğesi de bir liste olan bir demet tanımlamak istersek, her zamanki gibi virgülden yararlanacağız:
>>> a = (["elma", "armut", "erik"],)
5.3. Demetlerin Metotları¶
Daha önce de söylediğimiz gibi, demetler değiştirilemeyen veri tipleri oldukları için metot yönünden fakirdirler. Demetlerin hangi metotlara sahip olduğunu nasıl bulacağımızı biliyoruz:
>>> dir(tuple)
Bu komutun çıktısı içinde bizim ilgilendiğimiz metotlar count() ve index() metotlarıdır. Bu metotları listelerden de hatırlıyoruz. Bu metotlar listelerde ne işe yarıyorsa demetlerde de aynı işe yarar. Kısaca bakalım.
5.3.1. “count” metodu¶
Bu metot bir öğenin demet içinde kaç kez geçtiğini söyler bize:
>>> a = ("elma", "armut", "erik", "şeftali", "elma", "erik", "armut")
>>> a.count("elma")
5.3.2. “index” metodu¶
Bu metot ise bir demet öğesinin demet içindeki yerini bildirir. Yani o öğenin demet içinde kaçıncı sırada yer aldığını söyler:
>>> a = ("elma", "armut", "erik", "şeftali", "elma", "erik", "armut")
>>> a.index("elma")
0
Demek ki “elma” öğesi demet içinde “sıfırıncı” sırada bulunuyormuş. Bu arada gördüğünüz gibi, index() metodu bir öğeyi ilk geçtiği noktada tespit eder ve ilk bulduğu sıra numarasını verir. Dolayısıyla aynı demet içinde geçen öteki “elma” öğesinin kaçıncı sırada olduğuna bakmaz.
index() metodu, öğe adı dışında ikinci bir argüman daha alır. Yani parantez içinde belirttiğimiz öğe adının dışında bir sayı da belirterek, o öğenin kaçıncı tekrarının sırasını elde etmek istediğimizi belirleyebiliriz. Bu ne demek? Hemen bakalım:
>>> a = ("elma", "armut", "erik", "şeftali", "elma", "erik", "armut")
>>> a.index("elma", 2)
4
Bu defa “0” çıktısı yerine “4” çıktısını elde ettik. Parantez içinde belirttiğimiz “2” sayısı aracılığıyla Python’a şöyle dedik:
“Ey Python! Bana demet içinde geçen ikinci “elma” öğesinin sırasını söyle!”
Bu emri alan Python da demet içindeki ilk “elma” öğesini atlayıp ikinci “elma” öğesinin sırasına baktı. Böylece bize “4” çıktısını verdi. Demek ki demet içindeki ikinci “elma” öğesinin sıra numarası 4 imiş...
Demetlerin bize sunduğu metotlar bunlardan ibarettir. Bu bölümde demetlerin index() ve count() metotlarını incelediğimize göre, artık yolumuza devam edebiliriz...
5.4. Demetleme ve Demet Çözme¶
Bu bölümde demetlerle ilgili olarak daha önce öğrendiğimiz bazı şeylere farklı bir gözle bakacağız. Tabii bu arada yeni şeyler de öğreneceğiz. Bu bölümün amacı, demetlerle ilgili olarak şimdiye kadar öğrendiklerimize bir nevi “ad koymak”tan ibaret olacaktır.
Bu bölümün konusu “demetleme” (tuple packing) ve “demet çözme” (tuple unpacking). Öncelikle demetlemeden bahsedelim. Aslında şimdiye kadar birkaç kez “demetleme” örneği gördük. Şimdi bu gördüğümüz şeyi iyi bir tanımlayacağız.
Demetleri nasıl tanımlayacağımızı biliyoruz:
>>> demet = ("elma", 10, ["su", "ekmek", "zeytin"])
Burada, içinde farklı veri tipleri barındıran bir demet oluşturduk. Baştan beri tekrar tekrar söylediğimiz gibi demetler değiştirilemeyen veri tipleridir. Ama yukarıdaki örnekten de göreceğiniz gibi, demetlerin içine, değiştirilebilen veri tiplerini de yerleştirebiliyoruz. Örneğin yukarıda, değiştirilebilen bir veri tipi olan listeleri demetimizin içine yerleştirdik. Demetin kendisi değiştirilemese de, demetin barındırdığı liste öğelerinin değiştirilebileceğini biliyoruz.
Yukarıda verdiğimiz örnek basit bir demet tanımlama işlemidir. Şimdi vereceğimiz örnek ise bir “demetleme” (tuple packing) işlemidir:
>>> demet = "elma", (1, 2, 3, 4), ["kestane", "armut", "çilek"]
Burada yaptığımız şey, birbirinden farklı veri tiplerini alıp tek bir demet haline getirmekten ibaret... İşte bu işleme kısaca “demetleme” adı veriliyor. Çok özel bir yanı yok yani... Bu işlemin pek özel bir yanı olmasa da bu işlemin tersi olan “demet çözme” (tuple unpacking) işleminin güzel yanları vardır:
>>> demet = ("elma", (1, 2, 3, 4), ["kestane", "armut", "çilek"])
>>> a, b, c = demet
İşte burada yaptığımız şey de “demet çözme” işlemine bir örnektir. “a, b, c, = demet” şeklinde demetimizi çözdükten sonra artık şu şekilde öğelere erişebiliriz:
>>> a
'elma'
>>> b
(1, 2, 3, 4)
>>> c
['kestane', 'armut', 'çilek']
Bu işlemi normal bir değişken tanımlayarak da yapabilirsiniz:
>>> demet = 1, 2, 3, 4
>>> a, b, c, d = demet
Tabii daha önceki bölümlerde gördüğümüz gibi, birden fazla öğeye sahip bir değişken tanımladığımızda aslında daha ziyade bir demet tanımlamış oluyoruz. İsterseniz “type(demet)” komutuyla yukarıdaki “demet” değişkeninin tipini sorgulayarak bunu kendi gözlerinizle görebilirsiniz...
5.5. Döngülenebilir Nesneleri Çözme¶
Bu bölümde demetlere özgü olmayan bir konuya değineceğiz. Bu konuyu buraya almamın nedeni, konu demetlere özgü olmasa da demetlerle de bağlantısının bulunması, yapısı itibariyle demetleri de ilgilendirmesidir... Ayrıca bu bölüm bir bakıma bir önceki bölümün devamı olarak da düşünülebilir. Çünkü burada da temel olarak aynı kavramlardan bahsedeceğiz.
Bölümümüzün konusu “Döngülenebilir nesneleri çözme”. İngilizce’de buna “Iterable Unpacking” diyorlar. Peki ne demek bu “döngülenebilir nesneleri çözme” denen şey?
Öncelikle burada “döngülenebilir nesne” kavramından bahsetmemiz gerekiyor. İngilizce’de “iterable” olarak adlandırılan döngülenebilir nesneler kabaca “üzerinde döngü kurulabilen herhangi bir şey” olarak tarif edilebilir. Mesela karakter dizileri döngülenebilen nesnelerdir. Ama sayılar döngülenebilen nesneler değildir. Peki bir nesnenin döngülenebilip döngülenemeyeceğini nasıl anlayacağız? Çok basit. Bunun için kullanabileceğimiz ayrı bir fonksiyon bulunur Python’da... Bu fonksiyonun adı iter():
>>> iter("elma")
<str_iterator object at 0x00E4B8F0>
Bu komuttan elde ettiğimiz çıktı “elma” karakter dizisinin bir “döngülenebilir nesne” olduğunu söylüyor bize. Elde ettiğimiz çıktıya göre, “elma” karakter dizisi, “bellekte bulunduğu adres 0x00E4B8F0 olan bir döngülenebilir nesne” imiş... Bir de şuna bakalım:
>>> iter(10)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: 'int' object is not iterable
Burada en son satırda gördüğümüz “int object is not iterable” ifadesinden anlıyoruz ki sayılar döngülenebilir nesneler değilmiş... Dolayısıyla buradan şu sonucu çıkarıyoruz: Python’da karakter dizileri döngülenebilirken, sayılar döngülenemez. Yani karakter dizileri üzerinde mesela bir for döngüsü kurabiliriz, ama sayıların üzerinde bir for döngüsü kuramayız...
Konumuz demetler olduğuna göre, bir de demetlerin durumuna bakalım:
>>> iter(())
<tuple_iterator object at 0x00E4B910>
Burada demetlerin ayırt edici özelliği olan “()” işaretlerini kullandığımıza dikkat edin. Listeler için ise şöyle bir şey yapabiliriz:
>>> iter([])
<list_iterator object at 0x00E4B8F0>
Demek ki tıpkı demetler gibi, listeler de döngülenebilir nesnelermiş...
“Döngülenebilir Nesneleri Çözme” ifadesinin “Döngülenebilir Nesne” kısmını anladığımıza göre, gelelim bu nesneyi “çözme” meselesine... Döngülenebilir nesneleri çözmeyi aslında biliyoruz. Yukarıda dediğimiz gibi, demetler bir döngülenebilir nesnedir. Geçen bölümde demetlerin nasıl çözüleceğini (tuple unpacking) gördük. Dolayısıyla döngülenebilir nesneleri nasıl çözeceğimizi de tahmin edebiliriz... Zira demetler de bir döngülenebilir nesne olduğu için, “demet çözme” işleminin kendisi de aslında bir “döngülenebilir nesne çözme” işlemidir...
Hatırlarsanız demet çözme işlemini şu şekilde yapıyorduk:
>>> demet = (0, 1, 2)
>>> a, b, c = demet
Elbette konumuz demetler olduğu için örneğimizi önce bir demet tanımlayarak yaptık. Ama tabii ki illa demet tanımlamak zorunda değiliz. Yukarıdaki kodları şöyle de yazabiliriz:
>>> aralık = range(3)
>>> a, b, c = aralık
Öncelikle burada tanımladığımız şeyin bir demet olmadığına dikkatinizi çekmek isterim. “aralık” değişkenine type() fonksiyonunu uygularsanız bu verinin tipinin “tuple” olmadığını göreceksiniz...
Ayrıca burada tek tek “0, 1, 2” yazmak yerine, range() fonksiyonunun bize sunduğu kolaylıktan yararlandığımıza da dikkat edin...
Demetimizi veya aralığımızı tanımladıktan sonra a, b ve c değişkenlerini kullanarak demetin veya aralığın öğelerini tek tek yazdırabiliriz. Burada önemli nokta, eşitliğin sol tarafındaki nesne sayısı ile sağ tarafındaki nesne sayısının aynı olmasıdır. Yani sol tarafta “a”, “b” ve “c” gibi üç adet nesneye karşılık, sağ tarafta da “0”, “1” ve “2” gibi üç adet öğe var. Bu arada yukarıdaki kodları istersek şöyle de yazabiliriz elbette:
>>> a, b, c = range(3)
Bunu böyle yazdıktan sonra normal bir şekilde “a”, “b” ve “c” değişkenlerini kullanarak 0’dan 3’e kadar olan sayıları ekrana dökebiliriz.
Tanımı gereği, döngülenebilir nesneleri çözebilmek için, eşitliğin sağ tarafında takdir edersiniz ki döngülenebilir bir nesne olması gerekiyor... Mesela bu bölümün başında sayıların döngülenemediğini öğrenmiştik. Dolayısıyla şöyle bir şey yazamayız:
>>> a, b, c = 5
TypeError: 'int' object is not iterable
Bu hata bize “int” nesnesinin döngülenemeyeceğini söylüyor. Buradaki sorun eşitliğin sol ve sağ tarafındaki öğe sayısının aynı olmamasından kaynaklanmıyor. Sebep “int”, yani sayı veri tipinin döngülenemez bir nesne olması... Bu durumu daha net olarak şu örnekte görebiliriz:
>>> a, b, c = "su"
ValueError: need more than 2 values to unpack
Gördüğünüz gibi burada aldığımız hata farklı. Buradaki sorun eşitliğin sol ve sağ tarafında aynı sayıda öğe olmamasından kaynaklanıyor. Yoksa “su” karakter dizisi döngülenebilir bir nesne olduğu için öğe sayısını tutturmamız yeterli olacaktır. Zaten aldığımız hata, çözme işlemi için 2’den fazla değer gerektiğini söylüyor bize...
>>> a, b, c = "Can"
“Peki ben “a”, “b” ve “c” değişkenlerinin üçüne birden tek değer vermek istiyorsam ne yapacağım?” diye soruyor olabilirsiniz... Yani mesela hem a, hem b, hem de c değişkeninin değerinin “Can” olmasını istersek bunu nasıl yapacağız? Şöyle yapacağız:
>>> a = b = c = "Can"
Ancak şöyle bir deneme sizi hüsrana uğratabilir:
>>> a = b = c = 1, 2, 3
Burada her bir değişken 1, 2 ve 3 sayılarının üçünü birden içine alacaktır. Yani mesela “a” komutunu verdiğimizde şöyle bir çıktı elde edeceğiz:
>>> a
(1, 2, 3)
Aldığımız bu çıktı, neden istediğimiz gibi bir çıktı elde edemediğimizi aslında açıklıyor. Dikkat ederseniz aldığımız çıktının veri tipi bir demettir. İsterseniz a değişkenine type() fonksiyonunu uygulayarak bunu kendiniz de doğrulayabilirsiniz. Zira yukarıda yaptığımız şey aslında bir önceki bölümde öğrendiğimiz “demetleme” (tuple packing) işleminin ta kendisidir... Demetleme işlemini yaptıktan sonra isterseniz bu demeti çözebilirsiniz de...
>>> bir, iki, üç = a
>>> bir
1
>>> iki
2
>>> üç
3
Şimdiye kadar verdiğimiz örneklerde eşitliğin sol ve sağ tarafının aynı sayıda öğe içermesi gerekiyordu. Peki ya diyelim ki elimizde şöyle bir demet var:
>>> fedailer = ("Ahmet", "Mehmet", "Özcan", "Kezban", "Süreyya", "Cevat")
Yapmak istediğimiz şey bu demeti “ilk”, “orta” ve “son” olarak gruplandırmak olsun... Bu işlemi acaba nasıl yapmalıyız?
İsteğimizi gerçekleştirmek için iki yöntem var önümüzde. Birinci yöntemde Python’daki “dilimleme” (slicing) özelliğinden yararlanabiliriz:
>>> ilk, orta, son = fedailer[:1], fedailer[1:-1], fedailer[-1]
Öğeleri bu şekilde tanımladıktan sonra “ilk”, “orta” ve “son” değişkenlerini kullanarak her bir grubu ayrı ayrı yazdırabiliriz.
Gelelim ikinci yönteme... Bu ikinci yöntem Python 3.0 ile birlikte gelen bir özelliktir. Python’un 3.0’dan önceki sürümlerinde bu özellik bulunmaz:
>>> ilk, *orta, son = fedailer
>>> ilk
'Ahmet'
>>> orta
['Mehmet', 'Özcan', 'Kezban', 'Süreyya']
>>> son
'Cevat'
Gördüğünüz gibi, Python 3.0 ile birlikte yukarıdaki işlevi çok daha basit ve temiz bir şekilde yerine getirebiliyoruz. Burada “*” işaretinden yararlandığımıza dikkat edin. Bu tür ifadelere Python’da “starred expressions” (yıldızlı ifadeler) adı verilir. Python 3.0 ile birlikte bu yıldızlı ifadeler daha geniş bir kullanım alanına kavuştu. Hatta print() fonksiyonu içinde bile bu yıldızlı ifadelerden yararlanabiliriz. Yıldızlı ifadelerin print() fonksiyonunda kullanımı ile ilgili örnekleri birkaç bölüm sonra göreceğiz...
Yukarıdaki örnekte kullandığımız yıldızlı ifade, “ilk” ve “son” adlı değişkenler ile belirlenen öğelerin dışında kalan öteki bütün öğeleri tanımlayabilmemizi sağladı. Ayrıca burada yıldızlı ifade ile elde ettiğimiz kısmın bir liste olduğuna da dikkat edin. Burada normal olarak liste yerine demet verilmesi beklenebilirdi, ama çıktı üzerinde daha kolay işlem yapılabilmesi için Python geliştiricileri buradaki yıldızlı ifadenin çıktısının liste veri tipinde olmasını uygun görmüşlerdir... Gerçekten de değiştirilebilir (mutable) bir veri tipi olan listeler üzerinde işlem yapmak, değiştirilemeyen (immutable) bir veri tipi olan demetler üzerinde işlem yapmaktan çok daha kolaydır.
Döngülenebilir nesneleri çözme işleminin bu genişletilmiş haline ilişkin bütün özellikler ve bu yeni işlevin gerekçeleri, http://www.python.org/dev/peps/pep-3132/ adresinde bulunan PEP 3132‘de açıklanmıştır... Eğer bu konuyla ilgili olarak İngilizce kaynaklarda arama yapmak isterseniz, kullanmanız gereken ifade “Extended Iterable Unpacking” olacaktır...
Böylelikle Python’da “demetler” konusunu da bitirmiş olduk. Bu bölümde pek çok şey öğrendik. Bu öğrendiklerimizi birkaç kez gözden geçirerek bilgilerimizi pekiştirme yoluna gitmemiz, ilerde göreceğimiz konuları daha iyi kavrayabilmek bakımından oldukça faydalı olacaktır.