5. Veri Yapıları
Bu bölümde öğrendiğiniz bazı şeyler daha ayrıntılı açıklanmakta ve bazı yeni konulara da değinilmektedir.
5.1. Listeler Üzerine Daha Fazla Bilgi
Liste veri türünün birkaç yöntemi daha var. İşte liste nesnelerinin bütün yöntemleri:
-
list.
append
(x
) -
Listenin sonuna bir eleman ekler;
a[len(a):] = [x]
ifadesine denktir. -
list.
extend
(L
) -
Listeyi verilen listedeki tüm elemanları ekleyerek genişletir;
a[len(a):] = L
ifadesine denktir. -
list.
insert
(i, x
) -
Belirtilen konuma bir eleman yerleştirir. İlk bağımsız değişken elemanın yerleştirileceği indistir.
a.insert(0, x)
ifadesix
'i listenin başına yerleştirir, vea.insert(len(a), x)
ifadesia.append(x)
ifadesine denktir. -
list.
remove
(x
) -
Liste içinde değeri
x
olan ilk elemanı listeden siler. Böyle bir öğe yok iseValueError
istisnası oluşur. -
list.
pop
([i
]) -
Belirtilen konumdaki elemanı listeden siler ve bunu geri döndürür. Eğer bir indis belirtilmezse,
a.pop()
listedeki son elemanı siler ve döndürür. (i
etrafındaki köşeli ayraçlar bu bağımsız değişkenin seçimlik olduğunu belirtir. Bu yazım biçimini Python belgelerinde sıkça görebilirsiniz.) -
list.
clear
() -
Listenin tüm elemanlarını siler.
del a[:]
işlemine denktir. -
list.
index
(x
[,ilk
[,son
]]) -
Değeri
x
olan ilk elemanın indisini döndürür. Böyle bir öğe yok iseValueError
istisnası oluşur.İsteğe bağlı bağımsız değişkenler
ilk
veson
, dilim gösterimindeki gibi yorumlanır ve aramayı belirli bir aralıkla sınırlamak için kullanılır. Döndürülen indis,ilk
'e göre değil listenin başlangıcına göre hesaplanır. -
list.
count
(x
) -
x
'in listedeki miktarını bulur ve bu değeri geri döndürür. -
list.
sort
(*[,key=None
,reverse=False
]) -
Listeyi kendi içinde sıralar. İsteğe bağlı bağımsız değişkenler anahtar kelime olarak belirtilebilir ve sıralamayı özelleştirmek için kullabılabilir.
key
ile yinelemedeki her öğeden bir karşılaştırma anahtarı çıkarmak için kullanılan tek bağımsız değişkenli bir işlev belirtilir (örneğin,key=str.lower
).None
öntanımlıdır (öğeler doğrudan karşılaştırılır).reverse
mantıksal bir değerdir.True
belirtilirse liste elemanları tersine sıralanır. -
list.
reverse
() -
Listenin sırasını kendi içinde tersine çevirir.
-
list.
copy
() -
Listenin sığ bir kopyasını döndürür.
a[:]
ifadesine denktir.
Liste yöntemlerinin çoğunu kullanan bir örnek:
>>>
meyveler = ['portakal', 'elma', 'armut', 'muz', 'kivi', 'elma', 'muz']>>>
meyveler.count('elma') 2>>>
meyveler.count('mandalina') 0>>>
meyveler.index('muz') 3>>>
meyveler.index('muz', 4) # 4. konumdan sonraki muzun konumunu bul 6>>>
meyveler.reverse()>>>
meyveler ['muz', 'elma', 'kivi', 'muz', 'armut', 'elma', 'portakal']>>>
meyveler.append('üzüm')>>>
meyveler ['muz', 'elma', 'kivi', 'muz', 'armut', 'elma', 'portakal', 'üzüm']>>>
meyveler.sort()>>>
meyveler ['armut', 'elma', 'elma', 'kivi', 'muz', 'muz', 'portakal', 'üzüm']>>>
meyveler.pop() 'üzüm'
5.1.1. Listelerin Yığın Olarak Kullanılması
Liste yöntemleri listelerin kolayca yığın olarak kullanılmasını
sağlar. Yığına son giren eleman ilk çıkar. Yığının üzerine
eleman eklemek için append()
ve en üstteki
elemanı almak için indis belirtmeden pop()
kullanılır. Örnek:
>>>
yigin = [3, 4, 5]>>>
yigin.append(6)>>>
yigin.append(7)>>>
yigin [3, 4, 5, 6, 7]>>>
yigin.pop() 7>>>
yigin [3, 4, 5, 6]>>>
yigin.pop() 6>>>
yigin.pop() 5>>>
yigin [3, 4]
5.1.2. Listelerin Kuyruk Olarak Kullanılması
Listeleri kuyruk olarak da kullanmak mümkün. Bir kuyrukta ilk eklenen
eleman ilk alınan elemandır (ilk giren ilk çıkar). Kuyruğun sonuna
bir eleman eklemek için append()
kullanılır.
Sıranın başından bir eleman almak için ise 0 indisi ile
pop()
kullanılır. Örnek:
>>>
kuyruk = ["Ali", "Veli", "Deli"]>>>
kuyruk.append("Küpeli") # Küpeli kuyrukta>>>
kuyruk.append("Aylin") # Aylin kuyrukta>>>
kuyruk.pop(0) 'Ali'>>>
kuyruk.pop(0) 'Veli'>>>
kuyruk ['Deli', 'Küpeli', 'Aylin']
5.1.3. İşlevsel Yazılım Geliştirme Araçları
Listelerle kullanıldığında çok faydalı olan yerleşik işlevler vardır:
filter()
, map()
, ve
reduce()
.
filter(işlev, sıra)
sıra içerisinden
işlev(eleman)
'ın doğru sonuç verdiği elemanların
bulunduğu (mümkünse aynı türden) bir sıra geri döndürür. Örneğin,
bazı asal sayıları hesaplamak için şöyle yapılabilir:
>>>
def f(x): return x % 2 != 0 and x % 3 != 0...
>>>
filter(f, range(2, 25)) [5, 7, 11, 13, 17, 19, 23]
map(işlev, sıra)
sıranın her elemanı için
işlev(sıra)
çağırır ve geri döndürülen değerlerin
oluşturduğu listeyi geri döndürür. Örneğin bazı sayıların küplerini
hesaplamak için şu yol izlenebilir:
>>>
def cube(x): return x*x*x...
>>>
map(cube, range(1, 11)) [1, 8, 27, 64, 125, 216, 343, 512, 729, 1000]
map(işlev, sıra)
ifadesinde birden fazla sıra da
kullanılabilir; ancak bu durumda işlev sıra sayısı kadar bağımsız
değişkene sahip olmalıdır. işlev
her sıranın uygun
elemanını bir bağımsız değişken olarak alır; ancak sıralardan biri kısa
ise eksik elemanlar için işleve None
bağımsız
değişkeni aktarılır. Eğer işlev adı için de None
kullanılırsa bağımsız değişkenlerini döndüren bir işlev etkisi yaratılır.
Bu iki özel durumu birleştirerek
map(None, list1, list2)
ifadesi ile bir çift diziyi
çiftlerden oluşan bir diziye çevirebiliriz. Örnek:
>>>
sira = range(8)>>>
def kare(x): return x*x...
>>>
map(None, sira, map(kare, sira)) [(0, 0), (1, 1), (2, 4), (3, 9), (4, 16), (5, 25), (6, 36), (7, 49)]
reduce(işlev, sıra)
ifadesi tek bir değer geri
döndürür. Bu değer şöyle elde edilir: iki bağımsız değişkenli işleve
sıranın ilk iki elemanı bağımsız değişken olarak verilir, sonra da elde
edilen sonuç ile sıranın sonraki elemanı bağımsız değişken olarak
verilir, daha sonra yine elde edilen sonuç ile bir sonraki eleman işleve
verilir ve bu işlem bütün elemanlar için tekrarlanır. Örneğin 1'den 10'a
kadar olanlar böyle toplanabilir:
>>>
def topla(x,y): return x+y...
>>>
reduce(topla, range(1, 11)) 55
Sırada sadece bir eleman var ise bunun değeri geri döndürülür; sıra boş ise bir istisna oluşur (exception).
Başlangıç değerini bildirmek için üçüncü bir bağımsız değişken kullanılabilir. Bu durumda işleve ilk olarak başlangıç değeri ve sıranın ilk elemanına uygulanır ve diğer elemanlar ile devam eder. Örnek:
>>>
def sonuc(sira):...
def topla(x,y): return x+y...
return reduce(topla, sira, 0)...
>>>
sonuc(range(1, 11)) 55>>>
sonuc([]) 0
5.1.4. Liste Üreteçleri
Liste üreteçleri map()
, filter()
ve/veya lambda
işlevlerini kullanmadan liste
yaratmanın kısa bir yoludur. Bu yolla yaratılan liste tanımı genellikle
daha kolay anlaşılır olur. Bir liste üreteci bir ifade ve bir
for
döngüsü ile bunları izleyen sıfır ya da daha
fazla for
veya if
ifadelerinden
oluşur. Sonuç kendisini izleyen for
ve
if
bağlamında değerlendirilen ifadeden oluşan bir
listedir. Eğer ifade bir demete (değişmez liste [tuple]) dönüşecekse
parantez içinde yazılmalıdır.
>>>
freshfruit = [' muz', ' loganberry ', 'passion fruit ']>>>
[weapon.strip() for weapon in freshfruit] # elemanları saran boşlukların atıldığı yeni bir liste ['muz', 'loganberry', 'passion fruit']>>>
vec = [2, 4, 6]>>>
[3*x for x in vec] [6, 12, 18]>>>
[3*x for x in vec if x > 3] [12, 18]>>>
[3*x for x in vec if x < 2] []>>>
[{x: x**2} for x in vec] # sözlüklerden oluşan bir liste [{2: 4}, {4: 16}, {6: 36}]>>>
[[x,x**2] for x in vec] [[2, 4], [4, 16], [6, 36]]>>>
[x, x**2 for x in vec] # hata - demet için parantez gerekir File "<stdin>", line 1, in ? [x, x**2 for x in vec] ^ SyntaxError: invalid syntax>>>
[(x, x**2) for x in vec] [(2, 4), (4, 16), (6, 36)]>>>
vec1 = [2, 4, 6]>>>
vec2 = [4, 3, -9]>>>
[x*y for x in vec1 for y in vec2] [8, 6, -18, 16, 12, -36, 24, 18, -54]>>>
[x+y for x in vec1 for y in vec2] [6, 5, -7, 8, 7, -5, 10, 9, -3]>>>
[vec1[i]*vec2[i] for i in range(len(vec1))] [8, 12, -54]
Liste üreteçlerinin for
döngülerine benzer davranması
için, döngü değişkenine yapılan atamalar üreteç dışında da görünürler:
>>>
x = 100 # bu değişecek>>>
[x**3 for x in range(5)] [0, 1, 8, 27, 64]>>>
x 4 # range(5) için son değer >>
5.2. del
Deyimi
del
deyimi ile bir listeden indisi verilen bir
eleman silinebilir. Bu deyim ile bir listeden dilimler de silinebilir
(bunu daha önce dilimlere boş bir liste atayarak yapmıştık). Örnek:
>>>
a [-1, 1, 66.6, 333, 333, 1234.5]>>>
del a[0]>>>
a [1, 66.6, 333, 333, 1234.5]>>>
del a[2:4]>>>
a [1, 66.6, 1234.5]
del
deyimi tamamen silmek için de kullanılabilir:
>>>
del a
Bu aşamadan sonra a
ismine başvuru bir hatadır
(aynı isme başka bir değer atanana kadar). Daha sonra del
için başka kullanım alanları da göreceğiz.
5.3. Demetler (tuples)
Listelerin ve dizgelerin indisleme ve dilimleme gibi pek çok ortak özellikleri olduğunu grdük. Bunlar sıra şeklindeki iki veri türüdür. Python gelişmekte olan bir dil; diğer sıra şeklindeki veri türleri de Python'a eklenebilir. Demet de başka bir sıra şekilli standart veri türüdür.
Bir demet virgül ile ayrılmış bir kaç değerden oluşur.
>>>
t = 12345, 54321, 'merhaba!'>>>
t[0] 12345>>>
t (12345, 54321, 'merhaba!')>>>
# demetler iç içe kullanılabilirler :...
u = t, (1, 2, 3, 4, 5)>>>
u ((12345, 54321, 'merhaba!'), (1, 2, 3, 4, 5))
Gördüğünüz gibi çıktıda demetler daima parantez içinde görünürler; ki iç içe geçmiş demetler belli olsun. Demetler parantezli veya parantezsiz olarak yazılabilirler; ancak parantezler genelikle gereklidirler (özellikle de demet daha büyük bir ifadenin içinde geçiyorsa).
Demetlerin pekçok kullanım alanı var: (x, y)
koordinat
çifti, veri tabanındaki işçi kayıtları vb. gibi. Demetler de dizgeler
gibi değerleri değiştirilemez veri türleridir; bunların elemanlarına
atama yapılamaz (fakat dilimleme ve birleştirme aracılığı ile bu etki
sağlanabilir). Ayrıca değiştirilebilen elemanlardan oluşan demetler
oluşturmak da mümkündür (örnek: listelerden oluşan bir demet).
Sıfır veya bir elemanlı demetlerin oluşturulması ile ilgili özel bir problem var: bunların ifade edilmesini sağlayan sözdizim biraz acayip. Boş demetler bir çift boş parantez ile ifade edilir. Tek elemanı olan bir demet için ise elemandan sonra bir virgül kullanılır (tek bir değeri parantez içine almak yeterli değildir). Çirkin ama etkili. Örnek:
>>>
bos = ()>>>
tekOge = 'merhaba', # <--satır sonundaki virgüle dikkat>>>
len(bos) 0>>>
len(tekOge) 1>>>
tekOge ('merhaba',)
t = 12345, 54321, 'merhaba!'
ifadesi demetleme
(tuple packing) işlemine bir örnektir: 12345, 54321
ve
'merhaba!'
değerleri bir demet içinde toplanmışlardır.
Bu işlemin tersi de mümkün:
>>>
x, y, z = t
Doğal olarak, buna demet açma (sequence unpacking) deniyor. Demet açma sol taraftaki değişken sayısının sıra içindeki öğe sayısına eşit olmasını gerektirir. Çoklu değer atama işleminin aslında demetleme ve demet açmanın bir bileşimi olduğuna dikkat edin.
Burada küçük bir asimetri var: birden fazla değeri demetleme her zaman bir demet oluşturur ve demet açma herhangi bir sıra için yapılabilir. Örnek:
>>>
paket = 'xyz' # bir dizge>>>
a,b,c = paket>>>
a 'x'>>>
b 'y'>>>
c 'z'
5.4. Sözlükler (Çağrışımlı Listeler)
Python'da bulunan bir diğer faydalı veri türü de sözlüktür. Sözlükler
diğer yazılımlama dillerinde ``çağrışımlı bellek'' (associative memory)
veya ``çağrışımlı dizi'' (associative array) olarak bilinir.
Sayılarla indislenen sıralardan farklı olarak, sözlükler anahtarlar
(key) ile indislenir. Anahtar değiştirilemeyen türdeki herhangi bir
veri türünde olabilir. Sayılar ve dizgeler her zaman anahtar olabilir.
Demetler de sayılar, dizgeler veya demetler içerdikleri sürece
anahtar olabilir. Bir demet doğrudan ya da dolaylı olarak değiştirilebilir
bir nesne içeriyorsa anahtar olarak kullanılamaz. Listeler anahtar
olamazlar, çünkü append()
ile extend()
yöntemleri, dilimleme ve indise değer atama ile değiştirilebilir.
Bir sözlük anahtar : değer
çiftlerinden oluşur. Bir
anahtar sözlükte sadece bir defa bulunabilir. Bir çift çengelli parantez
boş bir sözlük yaratır : {}
. Çengelli parantezlerin
içine virgülle ayrılmış anahtar : değer
çiftleri
koymak anahtar ve değer çiftlerine ilk değerlerini verir. Çıktıya da
sözlükler aynı şekilde yazılır.
Sözlüklerle ilgili ana işlemler bir değerin bir anahtar ile saklanması
ve anahtar verildiğinde değerin bulunmasıdır. del
kullanarak bir anahtar : değer
çiftini silmek mümkündür.
Zaten mevcut olan bir anahtar kullanarak bir değer eklerseniz bu anahtarla
bağlantılı eski değer unutulur. Mevcut olmayan bir anahtar ile değer
istemek hatalıdır.
Sözlük nesnesinin keys()
yöntemi listedeki bütün
anahtarların listesini rasgele sıralı olarak geri döndürür (sıralamak
isterseniz listenin sort()
yönteminden faydalanabilirsiniz).
Bir anahtarın sözlükte olup olmadığını görmek için sözlüğün
has_key()
yöntemi kullanılır.
İşte sözlük kullanan küçük bir örnek:
>>>
tel = {'jack': 4098, 'sape': 4139}>>>
tel['guido'] = 4127>>>
tel {'sape': 4139, 'guido': 4127, 'jack': 4098}>>>
tel['jack'] 4098>>>
del tel['sape']>>>
tel['irv'] = 4127>>>
tel {'guido': 4127, 'irv': 4127, 'jack': 4098}>>>
tel.keys() ['guido', 'irv', 'jack']>>>
tel.has_key('guido') 1
dict()
işlevi anahtar-değer çiftlerinden oluşan demetlerden sözlükler üretir. Çiftlerin bir kalıba uyduğu durumlarda, liste üreteçleri ile anahtar-değer çiftleri kısaca ifade edilebilir.
>>>
dict([('sape', 4139), ('guido', 4127), ('jack', 4098)]) {'sape': 4139, 'jack': 4098, 'guido': 4127}>>>
dict([(x, x**2) for x in vec]) # liste üreteci kullanarak {2: 4, 4: 16, 6: 36}
5.5. Döngü Teknikleri
Sözlükler üzerinde döngüler kurarken o anki değer
items()
yöntemi ile aynı anda elde edilebilir.
>>>
knights = {'gallahad': 'the pure', 'robin': 'the brave'}>>>
for k, v in knights.items():...
print k, v...
gallahad the pure robin the brave
Bir sıra üzerinde dönerken konum indisi ve ona karşılık gelen değer de
enumerate()
işlevini kullanarak aynı anda elde edilebilir.
>>>
for i, v in enumerate(['tic', 'tac', 'toe']):...
print i, v...
0 tic 1 tac 2 toe
Aynı anda iki sıra üzerinde ilerlemek için ise zip()
işlevi ile bunlar çiftler haline getirilebilir.
>>>
sorular = ['adın', 'görevin', 'favori rengin']>>>
cevaplar = ['Adnan', 'Uyumak', 'Mavi']>>>
for s, c in zip(sorular, cevaplar):...
print 'Senin %s ne? %s.' % (s, c)...
Senin adın ne? Adnan. Senin görevin ne? Uyumak. Senin favori rengin ne? Mavi.
5.6. Koşullu İfadeler Üzerine Daha Fazla Bilgi
while
ve if
deyimlerinde kıyaslama
dışında da işleçler kullanılabilir.
in
ve not
kıyaslama işleçleri bir
değerin bir sıra içinde olup olmadığını sınar.
is
ve is not
işleçleri iki nesnenin
tamamen aynı nesne olup olmadıklarını sınarlar (bu sadece liste gibi
değiştirilebilir nesnelerde önemlidir).
Bütün kıyaslama işleçleri aynı önceliğe sahiptirler ve bu sayısal işleçlerinkinden düşüktür.
Kıyaslamalar zincirlenebilir: a < b == c
gibi.
Kıyaslamalar mantıksal işleçler and
ve
or
ile birleştirilebilirler ve kıyaslamanın sonucu
(ya da herhangi bir mantıksal ifade) not
ile
değillenebilir. Bunların hepsi de kıyaslama işleçlerinden düşük
önceliğe sahiptirler ve aralarında en yüksek öncelikli olan
not
ve en düşük öncelikli olan or
işleçidir. Örneğin A and not B or C
ifadesi
(A and (not B)) or C
ifadesine eştir. İstenen bileşimi
elde etmek için parantezler kullanılabilir.
and
ve or
mantıksal işleçlerine
kısa devre işleç de denir. Bunların bağımsız değişkenleri soldan sağa
değerlendirilir ve sonuç belli olur olmaz değerlendirme işlemi kesilir.
Örneğin A ve C doğru, fakat B yanlış olsun.
A and B and C
ifadesinde C ifadesi değerlendirilmez
(çünkü C'nin değeri sonucu değiştirmez). Genel olarak bir kısa devre
işleçi Bool
değil de genel bir değer gibi
kullanıldığında en son değerlendirilen bağımsız değişkenin değeri geri
döndürülür.
Bir kıyaslamanın ya da mantıksal ifadenin sonucunu bir değişkene atamak mümkündür:
>>>
string1, string2, string3 = '', 'Trondheim', 'Hammer Dance'>>>
non_null = string1 or string2 or string3>>>
non_null 'Trondheim'
C dilinin tersine, Python'da ifadelerin içinde atama olamayacağına dikkat edin. C yazılımcıları bundan şikayetçi olabilirler; ancak bu C yazılımlarında sık karşılaşılan bazı hataları engellemektedir (== yerine = yazmak gibi).
5.7. Listeler, Dizgeler ve Demetler Arasında Kıyaslama
Sıra nesneleri yine sıra şeklindeki diğer nesnelerle kıyaslanabilir. Önce ilk iki eleman kıyaslanır. Bunlar farklı ise sonuç belli olmuştur; eşit olmaları halinde sonraki iki eleman kıyaslanır ve sıralardan biri tükenene kadar bu işlem tekrarlanır. Eğer kıyaslanan iki öğe de sıra ise bunlar da kendi aralarında kıyaslanır. İki sıranın bütün öğeleri aynı bulunursa bu sıralar eşit kabul edilir. Eğer bir sıra diğerinin başından bir kısmı ile aynı ise kısa olan sıra küçük kabul edilir. Karakterlerin kıyaslanmasında ASCII karakter sırası kullanılır. Aynı türden sıraların kıyaslanmasına bazı örnekler :
(1, 2, 3) < (1, 2, 4) [1, 2, 3] < [1, 2, 4] 'ABC' < 'C' < 'Pascal' < 'Python' (1, 2, 3, 4) < (1, 2, 4) (1, 2) < (1, 2, -1) (1, 2, 3) == (1.0, 2.0, 3.0) (1, 2, ('aa', 'ab')) < (1, 2, ('abc', 'a'), 4)
Farklı türden nesnelerin kıyaslanmasının yasal olduğuna dikkat edin. Türler alfabetik sırayla dizilmiştir (ingilizce isimlerine göre). Yani: liste < dizge < demet (list < string < tuple).[69]
[69] Değişik türlerin kıyaslanmasına ilişkin kurallara güvenilmemeli; gelecek Python sürümlerinde bu kurallar değişebilir!