Liste, List Veri Yapısı - 2
14-0.23.00
Liste İçerisinde Liste
Bir listenin elemanı başka bir liste olabilir. Mesela
x = [1, [2, 3, 4], 5]
olabilir. Neden olmasın ki? Sonuçta liste de bir türdür ve listeler nasıl diğer türleri tutabiliyorsa kendi türlerini de tutabilirler.
x ------------> list_nesnesi
------------------> 1 (int)
------------------> list_nesnesi
-----------------> 2 (int)
-----------------> 3 (int)
-----------------> 4 (int)
------------------> 5 (int)
şeklinde bir bellek organizasyonu olmaktadır.
>>> x[1] is x[1][0]
False
>>> x = [1, [2, 3, 4], 5]
>>> len(x)
3
>>> type(x[0])
<class 'int'>
>>> x[0]
1
>>> type(x[1])
<class 'list'>
>>> x[1]
[2, 3, 4]
>>> x[1][2]
4
Bir listenin içerisindeki listenin elemanlarına ikinci bir köşeli parantez
ile erişebiliriz, yukarıdaki x[1][2]
ifadesi gibi.
Python’da Matrisler (Matrix)
14-0.36.50
Python’da matrisler iç içe listeler şeklinde temsil edilmektedir. Mesela
3x3
lük bir matris oluşturalım.
a = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
Elbette listeler farklı uzunlukta da olabilir, Python açısından bir engel yoktur.
a = [[1, 2, 3, 4], [5, 6], [7, 8, 9]] # geçerlidir.
Negatif İndeks Değerleri
14-0.44.00
Python’da liste elemanlarına []
operatörü ile erişirken negatif indeks
değerleri de verebiliriz, bu programlama dillerinde çok yaygın değildir ama yeni
dillerde yaygındır.
Eğer negatif bir değer verilirse gerçek indeks, listenin uzunluğu ile bu değer
toplanarak elde edilir. Yani i
bir negatif değer ise x[i]
ile bir elemana
erişmeye çalıştığımız zaman aslında x[len(x) + i]
elemanına erişmiş oluruz.
Örneğin:
>>> x[4]
5
>>> x[-1]
5
>>> x[4] is x[-1]
True
>>> x[0] is x[-5]
True
Eğer bir gerçekten mutlak değerce büyük bir negatif sayı verirsek bu sefer
len() + i
işleminin sonucu gerçekten negatif çıkabilir ve bu durumda
IndexError
exception oluşur.
>>> x[-10]
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
IndexError: list index out of range
İç içe dizilerde de bu özellik kullanılabilmektedir.
>>> a = [[10, 20, 30], [40, 50, 60], [70, 80, 90]]
>>> a[-1][-1]
90
Negatif indeksleme özelliği bazı durumlarda listeyi sondan başa doğru dolaşmak, uzunluğunu alıp tekrar hesaplama ile uğraşmamak gibi faydalar sağlayabilmektedir.
Dilimleme, Slicing
14-1.01.08
Bir liste içerisindeki bir grup elemanı yine bir liste olarak elde edebiliriz.
Buna Python’da slicing yani dilimleme denmektedir. İndeks erişimi gibi
dilimleme de []
içerisinde yapılmaktadır. Genel biçimi
x[start:stop]
VEYA
x[start:stop:step]
şeklindedir. step
kısmı belirtilmeyebilir. Dilimlemede start
indeksli eleman
dahil fakat stop
indeksli eleman ise dahil DEĞİLDİR. Dilimleme
sonucunda yeni bir liste oluşturulur. Bu 3 parametrenin de int
türden
ifadeler olması gerekmektedir.
Örneğin
>>> x = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
>>> x[2:5]
[3, 4, 5]
>>> x[2:5][0] is x[2]
True
yapılabilmektedir.
Slicing yaparken negatif indeks de kullanılabilmektedir.
>>> x[2:-5]
[3, 4, 5]
>>> x[-8:-5]
[3, 4, 5]
>>> x[-8:5]
[3, 4, 5]
gibi.
Slicing yaparken start
ya da stop
değerleri liste uzunluğundan büyük olursa
otomatik olarak limitlenmektedir. Burada bir exception oluşmamaktadır.
>>> x[2:100]
[3, 4, 5, 6, 7, 8, 9, 10]
>>> x[-200:2]
[1, 2]
gibi.
Eğer start
ve stop
değer girerken negatif değerler kullanıyorsak bu değer
len()
ile toplanup gerçek indeks bulunurken sonuç negatif çıkarsa bu değer
yerine 0
kullanılır. Yani çok büyük negatif değerler kullanırsak start
ya da stop
yerine aslında 0
yazmış olmaktayız.
Slicing yaparken :
nin soluna bir şey yazmazsak 0
yazmışız gibi olur. Sağına
bir şey yazmazsak da geri kalan hepsi yani len()
yazmışız demek. İki
tarafına da bir şey yazmazsak listenin hepsi anlamı çıkacaktır.
>>> x[:2]
[1, 2]
>>> x[:]
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
>>> x[2:]
[3, 4, 5, 6, 7, 8, 9, 10]
start
ile stop
aynı değerdeyse ya da start
değeri stop
tan büyükse
boş liste elde edilmektedir.
>>> x[2:2]
[]
>>> x[3:2]
[]
gibi.
Bir de ikinci :
atomu sağına konulabilecek step
değeri vardır. Bu, atlama
miktarını belirtmektedir. Yazılmazsa 1
değeri kabul edilir. Elde edilecek
değerlere hiçbir zaman stop
dahil olmaz.
>>> x[2:7:2] # indeks 2, 4, 6 alındı.
[3, 5, 7]
>>> x[2:8:3] # indeks 2, 5 alındı, 8 hariç bırakıldı.
[3, 6]
step
negatif değer de alabilir. Bu durumda ilerleme ters yönde olur. Bunun
anlamlı olması için start
değerinin stop
değerinden büyük olması gerekir.
Yine start
dahil, stop
hariç olmaktadır.
>>> x[7:2:-1]
[8, 7, 6, 5, 4]
step
negatif ise start
indeksinin boş bırakılması len() - 1
anlamına
gelmektedir.
>>> x[:5:-1]
[10, 9, 8, 7]
step
negatif ise stop
indeksinin boş bırakılması ise ilk elemana kadar
(ilk eleman dahil) anlamına gelmektedir.
>>> x[5::-1]
[6, 5, 4, 3, 2, 1]
Listeyi Ters Çevirme
Negatif step
ile bir listeyi ters çevirebiliriz ve [::-1]
bunun için
sıklıkla kullanılmaktadır.
>>> x[::-1]
[10, 9, 8, 7, 6, 5, 4, 3, 2, 1]
gibi.
Dilimleme Yolu ile Listenin Güncellenmesi
14-1.29.30
Dilimleme yani slice yöntemi ile liste elemanları güncellenebilir.
x[start:stop] = <dolaşılabilir nesne>
genel sentaksı ile yapılabilir. Burada basitlik açısından step
gösterilmemiştir. Sağ tarafın mutalaka dolaşılabilir yani iterable olması
gerekir.
>>> x = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
>>> x[2:4] = 20
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: can only assign an iterable
Yukarıdaki örnekte 20
yani int
iterable olmadığı için hata aldık.
Bu durumda önce dilimlenen elemanlar silinir, sonra onların yerine
dolaşılabilir nesnedeki elemanlar start
indeksinden itibaren yerleştirilir. Bu
işlemin aslında iki basamaklı olduğunu hatırlamak sonraki kısımlarda bazı
durumları anlamamızı kolaylaştıracaktır.
Silinen eleman sayısı ile dolaşılabilir nesnedeki eleman sayısı aynı olmak zorunda değildir.
>>> x[2:8] = [4]
>>> x
[1, 2, 4, 9, 10]
Burada [2:8]
ile geniş bir eleman silinmiş ama yerine daha az eleman
sokuşturulmuştur. Tersi de mümkündür:
>>> x[2:4] = [1, 2, 3, 4 ,5]
>>> x
[1, 2, 1, 2, 3, 4, 5, 10]
Biraz kafa karıştırıcı durumlar oluşabilmektedir:
>>> x = [1, 2, 1, 2, 3, 4, 5, 10]
>>> x[2:7] = [['alper', 'yazar']]
>>> x
[1, 2, ['alper', 'yazar'], 10]
Burada iç içe liste elde etmiş olduk.
Ya da
>>> x = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
>>> x[-1:] = ['alper', 'yazar']
>>> x
[1, 2, 3, 4, 5, 6, 7, 8, 9, 'alper', 'yazar']
Burada son eleman silindi ve yerine yeni listeden elemanları yerleştirdik.
Ya da
>>> x[1:1] = ['alper', 'yazar']
>>> x
[1, 'alper', 'yazar', 2, 3, 4, 5, 6, 7, 8, 9, 10]
Burada 1:1
ile hiçbir eleman seçemedik o yüzden silme yapmamış olduk sadece
yerleştirme yaptık. İlginç di mi? Bu bir metin editörde hiç metin seçmeyip,
cursor yerine CTRL-V
yapmaya benziyor.
Ya da
>>> x = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
>>> x[2:7:2] = [100, 200, 300]
>>> x
[1, 2, 100, 4, 200, 6, 300, 8, 9, 10]
Burada da silme ve yerleştirme atlaya atlaya yapıldı.
Eğer atladığımız durumda yerleştirmeye çalıştığımız kısım daha uzun olursa
ValueError
exception oluşmaktadır.
>>> x = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
>>> x[2:5:2] = [100, 200, 300]
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ValueError: attempt to assign sequence of size 3 to extended slice of size 2
ama step
belirtmezsek az silip çok sokuşturmak problem olmaz.
>>> x = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
>>> x[2:4] = [100, 200, 300]
>>> x
[1, 2, 100, 200, 300, 5, 6, 7, 8, 9, 10]
Benzer durup çok silip az sokuşturduğumuzda da oluşmaktadır.
>>> x = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
>>> x[2:5:2] = [100]
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ValueError: attempt to assign sequence of size 1 to extended slice of size 2
>>> x = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
>>> x[2:5] = [100]
>>> x
[1, 2, 100, 6, 7, 8, 9, 10]
Bu şekilde silme de yapabilmekteytiz. Dolaşılabilir nesnede hiç eleman yoksa bu durum silme anlamına gelecektir.
>>> x = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
>>> x[2:5] = []
>>> x
[1, 2, 6, 7, 8, 9, 10]
Niye böyle oluyor? Çünkü önce siliyor sonra iş yerleştirmeye gelince görüyor ki *Aaa, sokuşturacak hiçbir şey yok! Biz de efektif olarak silmiş oluyoruz.
Eğer step
negatif bir değer olursa bu sefer yerleştirme işlemi ters yönde
yapılır. Yine seçilen ve silinen eleman sayısı ile atanan eleman sayısının
aynı olması gerekmektedir.
>>> x = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
>>> x[5:2:-1] = [10, 20, 30]
>>> x
[1, 2, 3, 30, 20, 10, 7, 8, 9, 10]
Walrus, :=
, Operatörünün Kullanımı
Listelere atama yapılırken Walrus operatörü “şartlar uygunsa” kullanılabilmektedir.
>>> (x := [1, 2])
[1, 2]
Walrus operatörü ile []
ile subscript belirterek atama yapılamamaktadır.
>>> (x[0] := [1, 2])
File "<stdin>", line 1
(x[0] := [1, 2])
^^^^
SyntaxError: cannot use assignment expressions with subscript
>>> (x[0:1] := [1, 2])
File "<stdin>", line 1
(x[0:1] := [1, 2])
^^^^^^
SyntaxError: cannot use assignment expressions with subscript
14-2.04.04
💭 Yorumlar
Yorum altyapısı giscus tarafından (evet tarafından!) sağlanmaktadır. Yorum yazabilmek için GitHub hesabınız üzerinden giriş yapmanız gerekmektedir. Yorumlar, Github Discussions üzerinde saklanmaktadır.
869ff52f-c279-4f16-8054-5732bad91cbb