5. Veri Yapıları
****************

Bu bölüm, daha önce öğrendiğiniz bazı şeyleri daha ayrıntılı olarak
açıklamakta ve bazı yeni şeyler de eklemektedir.


5.1. Listeler Üzerine
=====================

Liste veri türünün bazı yöntemleri daha vardır.  Liste nesnelerinin
tüm metotları şunlardır:

list.append(x)

   Listenin sonuna bir öğe ekleyin. "a[len(a):] = [x]" ile eş
   değerdir.

list.extend(iterable)

   Listeyi iterable'daki tüm öğeleri ekleyerek genişletin.
   "a[len(a):] = iterable" ile eş değerdir.

list.insert(i, x)

   Verilen pozisyona bir öğe ekleyin.  İlk argüman, daha önce
   ekleyeceğiniz öğenin indeksidir, bu nedenle "a.insert(0, x)"
   listenin önüne ekler ve "a.insert(len(a), x)" komutu "a.append(x)"
   komutu ile eş değerdir.

list.remove(x)

   Değeri *x*'e eşit olan ilk öğeyi listeden kaldırır.  Böyle bir öğe
   yoksa "ValueError" hatası ortaya çıkar.

list.pop([i])

   Remove the item at the given position in the list, and return it.
   If no index is specified, "a.pop()" removes and returns the last
   item in the list. It raises an "IndexError" if the list is empty or
   the index is outside the list range.

list.clear()

   Listeden tüm öğeleri kaldırır.  "del a[:]" ile eş değerdir.

list.index(x[, start[, end]])

   Değeri *x*'e eşit olan ilk öğenin listedeki sıfır tabanlı indeksini
   döndürür. Böyle bir öğe yoksa "ValueError" hatası ortaya çıkar.

   İsteğe bağlı *start* ve *end* argümanları dilim gösteriminde olduğu
   gibi yorumlanır ve aramayı listenin belirli bir alt dizisiyle
   sınırlamak için kullanılır.  Döndürülen dizin, *start* bağımsız
   değişkeni yerine tam dizinin başlangıcına göre hesaplanır.

list.count(x)

   Listede *x* öğesinin kaç kez göründüğünü döndürür.

list.sort(*, key=None, reverse=False)

   Listenin öğelerini yerinde sıralayın (argümanlar sıralama
   özelleştirmesi için kullanılabilir, açıklamaları için bkz:
   "sorted()").

list.reverse()

   Listenin öğelerini yerinde ters çevirir.

list.copy()

   Listenin yüzeysel bir kopyasını döndürür. "a[:]" ile eş değerdir.

Liste yöntemlerinin çoğunu kullanan bir örnek:

   >>> fruits = ['orange', 'apple', 'pear', 'banana', 'kiwi', 'apple', 'banana']
   >>> fruits.count('apple')
   2
   >>> fruits.count('tangerine')
   0
   >>> fruits.index('banana')
   3
   >>> fruits.index('banana', 4)  # Find next banana starting at position 4
   6
   >>> fruits.reverse()
   >>> fruits
   ['banana', 'apple', 'kiwi', 'banana', 'pear', 'apple', 'orange']
   >>> fruits.append('grape')
   >>> fruits
   ['banana', 'apple', 'kiwi', 'banana', 'pear', 'apple', 'orange', 'grape']
   >>> fruits.sort()
   >>> fruits
   ['apple', 'apple', 'banana', 'banana', 'grape', 'kiwi', 'orange', 'pear']
   >>> fruits.pop()
   'pear'

Listeyi yalnızca değiştiren "insert", "remove" veya "sort" gibi
yöntemlerin hiçbir dönüş değeri yazdırmadığını fark etmiş
olabilirsiniz -- onlar varsayılan "None" değerini döndürürler. [1]
Bu, Python'daki tüm değiştirilebilir veri yapıları için bir tasarım
ilkesidir.

Fark edebileceğiniz bir başka şey de tüm verilerin sıralanamayacağı
veya karşılaştırılamayacağıdır.  Örneğin, "[None, 'hello', 10]"
sıralanamaz çünkü tamsayılar dizelerle karşılaştırılamaz ve *None*
diğer türlerle karşılaştırılamaz.  Ayrıca, tanımlanmış bir sıralama
ilişkisine sahip olmayan bazı türler de vardır.  Örneğin, "3+4j <
5+7j" geçerli bir karşılaştırma değildir.


5.1.1. Listeleri Yığın Olarak Kullanma
--------------------------------------

The list methods make it very easy to use a list as a stack, where the
last element added is the first element retrieved ("last-in, first-
out").  To add an item to the top of the stack, use "append()".  To
retrieve an item from the top of the stack, use "pop()" without an
explicit index.  For example:

   >>> stack = [3, 4, 5]
   >>> stack.append(6)
   >>> stack.append(7)
   >>> stack
   [3, 4, 5, 6, 7]
   >>> stack.pop()
   7
   >>> stack
   [3, 4, 5, 6]
   >>> stack.pop()
   6
   >>> stack.pop()
   5
   >>> stack
   [3, 4]


5.1.2. Listeleri Kuyruk Olarak Kullanma
---------------------------------------

Bir listeyi, eklenen ilk elemanın alınan ilk eleman olduğu bir kuyruk
olarak kullanmak da mümkündür ("ilk giren ilk çıkar"); ancak listeler
bu amaç için verimli değildir.  Listenin sonundan ekleme ve çıkarma
işlemleri hızlıyken, listenin başından ekleme veya çıkarma yapmak
yavaştır (çünkü diğer tüm öğelerin bir adım kaydırılması gerekir).

Bir kuyruk uygulamak için, her iki uçtan da hızlı ekleme ve çıkarma
yapmak üzere tasarlanmış "collections.deque" kullanın.  Örneğin:

   >>> from collections import deque
   >>> queue = deque(["Eric", "John", "Michael"])
   >>> queue.append("Terry")           # Terry arrives
   >>> queue.append("Graham")          # Graham arrives
   >>> queue.popleft()                 # The first to arrive now leaves
   'Eric'
   >>> queue.popleft()                 # The second to arrive now leaves
   'John'
   >>> queue                           # Remaining queue in order of arrival
   deque(['Michael', 'Terry', 'Graham'])


5.1.3. Liste Kavramaları
------------------------

Liste kavramaları, listeler oluşturmak için kısa bir yol sağlar.
Yaygın uygulamalar, her bir öğenin başka bir dizinin veya
yinelenebilir öğenin her bir üyesine uygulanan bazı işlemlerin sonucu
olduğu yeni listeler oluşturmak veya belirli bir koşulu karşılayan
öğelerin bir alt dizisini oluşturmaktır.

Örneğin, aşağıdaki gibi bir kareler listesi oluşturmak istediğimizi
varsayalım:

   >>> squares = []
   >>> for x in range(10):
   ...     squares.append(x**2)
   ...
   >>> squares
   [0, 1, 4, 9, 16, 25, 36, 49, 64, 81]

Bunun, "x" adında bir değişken yarattığına (veya üzerine yazdığına) ve
bu değişkenin döngü tamamlandıktan sonra da var olduğuna dikkat edin.
Kareler listesini, şunu kullanarak herhangi bir yan etki olmadan
hesaplayabiliriz:

   squares = list(map(lambda x: x**2, range(10)))

veya aynı şekilde:

   squares = [x**2 for x in range(10)]

ki bu daha kısa ve okunaklıdır.

Bir liste kavrayışı, bir ifade içeren parantezlerden ve ardından bir
"for" cümlesinden, ardından sıfır veya daha fazla "for" veya "if"
cümlesinden oluşur.  Sonuç, ifadenin kendisini takip eden "for" ve
"if" cümleleri bağlamında değerlendirilmesiyle elde edilen yeni bir
liste olacaktır. Örneğin, listcomp, eşit değillerse iki listenin
öğelerini birleştirir:

   >>> [(x, y) for x in [1,2,3] for y in [3,1,4] if x != y]
   [(1, 3), (1, 4), (2, 3), (2, 1), (2, 4), (3, 1), (3, 4)]

ve şuna eş değerdir:

   >>> combs = []
   >>> for x in [1,2,3]:
   ...     for y in [3,1,4]:
   ...         if x != y:
   ...             combs.append((x, y))
   ...
   >>> combs
   [(1, 3), (1, 4), (2, 3), (2, 1), (2, 4), (3, 1), (3, 4)]

Her iki kod parçacığında da "for" ve "if" ifadelerinin sıralamasının
aynı olduğuna dikkat edin.

Eğer ifade bir veri grubu ise (örneğin önceki örnekteki "(x, y)"),
parantez içine alınmalıdır.

   >>> vec = [-4, -2, 0, 2, 4]
   >>> # create a new list with the values doubled
   >>> [x*2 for x in vec]
   [-8, -4, 0, 4, 8]
   >>> # filter the list to exclude negative numbers
   >>> [x for x in vec if x >= 0]
   [0, 2, 4]
   >>> # apply a function to all the elements
   >>> [abs(x) for x in vec]
   [4, 2, 0, 2, 4]
   >>> # call a method on each element
   >>> freshfruit = ['  banana', '  loganberry ', 'passion fruit  ']
   >>> [weapon.strip() for weapon in freshfruit]
   ['banana', 'loganberry', 'passion fruit']
   >>> # create a list of 2-tuples like (number, square)
   >>> [(x, x**2) for x in range(6)]
   [(0, 0), (1, 1), (2, 4), (3, 9), (4, 16), (5, 25)]
   >>> # the tuple must be parenthesized, otherwise an error is raised
   >>> [x, x**2 for x in range(6)]
     File "<stdin>", line 1
       [x, x**2 for x in range(6)]
        ^^^^^^^
   SyntaxError: did you forget parentheses around the comprehension target?
   >>> # flatten a list using a listcomp with two 'for'
   >>> vec = [[1,2,3], [4,5,6], [7,8,9]]
   >>> [num for elem in vec for num in elem]
   [1, 2, 3, 4, 5, 6, 7, 8, 9]

Liste kavramaları karmaşık ifadeler ve iç içe geçmiş fonksiyonlar
içerebilir:

   >>> from math import pi
   >>> [str(round(pi, i)) for i in range(1, 6)]
   ['3.1', '3.14', '3.142', '3.1416', '3.14159']


5.1.4. İç İçe Liste Kavramaları
-------------------------------

Bir liste kavrayışındaki ilk ifade, başka bir liste kavrayışı da dahil
olmak üzere rastgele herhangi bir ifade olabilir.

Uzunluğu 4 olan 3 listeden oluşan bir liste olarak uygulanan 3x4'lük
bir matrisin aşağıdaki örneğini düşünün:

   >>> matrix = [
   ...     [1, 2, 3, 4],
   ...     [5, 6, 7, 8],
   ...     [9, 10, 11, 12],
   ... ]

Aşağıdaki liste kavraması satır ve sütunların yerlerini değiştirir:

   >>> [[row[i] for row in matrix] for i in range(4)]
   [[1, 5, 9], [2, 6, 10], [3, 7, 11], [4, 8, 12]]

Önceki bölümde gördüğümüz gibi, iç liste kavrayışı, onu takip eden
"for" bağlamında değerlendirilir, bu nedenle bu örnek şuna eş
değerdir:

   >>> transposed = []
   >>> for i in range(4):
   ...     transposed.append([row[i] for row in matrix])
   ...
   >>> transposed
   [[1, 5, 9], [2, 6, 10], [3, 7, 11], [4, 8, 12]]

ki bu da şununla aynıdır:

   >>> transposed = []
   >>> for i in range(4):
   ...     # the following 3 lines implement the nested listcomp
   ...     transposed_row = []
   ...     for row in matrix:
   ...         transposed_row.append(row[i])
   ...     transposed.append(transposed_row)
   ...
   >>> transposed
   [[1, 5, 9], [2, 6, 10], [3, 7, 11], [4, 8, 12]]

Gerçek dünyada, karmaşık akışlı ifadeler yerine yerleşik işlevleri
tercih etmelisiniz. Bu kullanım durumu için "zip()" fonksiyonu harika
bir iş çıkaracaktır:

   >>> list(zip(*matrix))
   [(1, 5, 9), (2, 6, 10), (3, 7, 11), (4, 8, 12)]

Bu satırdaki yıldız işaretiyle ilgili ayrıntılar için Argüman
Listelerini Açma bölümüne bakın.


5.2. "del" ifadesi
==================

There is a way to remove an item from a list given its index instead
of its value: the "del" statement.  This differs from the "pop()"
method which returns a value.  The "del" statement can also be used to
remove slices from a list or clear the entire list (which we did
earlier by assignment of an empty list to the slice).  For example:

   >>> a = [-1, 1, 66.25, 333, 333, 1234.5]
   >>> del a[0]
   >>> a
   [1, 66.25, 333, 333, 1234.5]
   >>> del a[2:4]
   >>> a
   [1, 66.25, 1234.5]
   >>> del a[:]
   >>> a
   []

"del" değişkenlerin tamamını silmek için de kullanılabilir:

   >>> del a

Bundan sonra "a" ismine referans vermek bir hatadır (en azından ona
başka bir değer atanana kadar).  Daha sonra "del" için başka
kullanımlar bulacağız.


5.3. Veri Grupları ve Diziler
=============================

Listelerin ve dizelerin indeksleme ve dilimleme işlemleri gibi birçok
ortak özelliğe sahip olduğunu gördük.  Bunlar *dizi* veri tiplerinin
iki örneğidir (bkz. Dizi Tipleri --- list, tuple, range).  Python
gelişen bir dil olduğu için başka dizi veri tipleri de eklenebilir.
Ayrıca başka bir standart dizi veri tipi daha vardır: *tuple*.

Bir veri grubu, virgülle ayrılmış bir dizi değerden oluşur, örneğin:

   >>> t = 12345, 54321, 'hello!'
   >>> t[0]
   12345
   >>> t
   (12345, 54321, 'hello!')
   >>> # Tuples may be nested:
   ... u = t, (1, 2, 3, 4, 5)
   >>> u
   ((12345, 54321, 'hello!'), (1, 2, 3, 4, 5))
   >>> # Tuples are immutable:
   ... t[0] = 88888
   Traceback (most recent call last):
     File "<stdin>", line 1, in <module>
   TypeError: 'tuple' object does not support item assignment
   >>> # but they can contain mutable objects:
   ... v = ([1, 2, 3], [3, 2, 1])
   >>> v
   ([1, 2, 3], [3, 2, 1])

Gördüğünüz gibi, çıktıda veri grupları her zaman parantez içine
alınır, böylece iç içe geçmiş veri grupları doğru şekilde yorumlanır;
parantezli veya parantezsiz olarak girilebilirler, ancak genellikle
parantezler gereklidir (eğer grup daha büyük bir ifadenin parçasıysa).
Bir veri grubunun öğelerine tek tek atama yapmak mümkün değildir,
ancak listeler gibi değiştirilebilir nesneler içeren veri grupları
oluşturmak mümkündür.

Veri grupları listelere benzer görünse de, genellikle farklı
durumlarda ve farklı amaçlar için kullanılırlar. Veri grupları
*immutable* 'dır ve genellikle paket açma (bu bölümün ilerleyen
kısımlarına bakınız) veya indeksleme (hatta "namedtuples" durumunda
öznitelik ile) yoluyla erişilen heterojen bir dizi eleman içerir.
Listeler *mutable* 'dır ve elemanları genellikle homojendir ve
listenin üzerinde yinelenerek erişilir.

Özel bir sorun, 0 veya 1 öğe içeren veri gruplarının oluşturulmasıdır:
söz diziminin bunlar ile başa çıkan bazı ekstra tuhaflıkları vardır.
Boş veri grupları boş bir parantez çifti ile oluşturulur; bir öğeli
bir veri grubu, bir değeri virgülle takip ederek oluşturulur (tek bir
değeri parantez içine almak yeterli değildir). Çirkin olsa da
etkilidir.  Örneğin:

   >>> empty = ()
   >>> singleton = 'hello',    # <-- note trailing comma
   >>> len(empty)
   0
   >>> len(singleton)
   1
   >>> singleton
   ('hello',)

"t = 12345, 54321, ‘hello!’" ifadesi bir *veri grubu paketleme*
örneğidir: "12345", "54321" ve "'hello!'" değerleri bir veri grubu
içinde bir araya getirilmiştir. Bu işlemin tersi de mümkündür:

   >>> x, y, z = t

Buna uygun bir şekilde *dizi açma (sequence unpacking)* denir ve sağ
taraftaki herhangi bir dizi için çalışır.  Dizi açma, eşittir
işaretinin sol tarafında dizideki eleman sayısı kadar değişken
olmasını gerektirir.  Çoklu atamanın aslında tuple paketleme ve dizi
açmanın bir kombinasyonu olduğunu unutmayın.


5.4. Kümeler
============

Python ayrıca *kümeler* için bir veri türü içerir.  Bir küme,
yinelenen öğeleri olmayan sırasız bir koleksiyondur.  Temel
kullanımları içerisinde üyelik testi ve yinelenen girdilerin elenmesi
yer alır.  Küme nesneleri ayrıca birleşim, kesişim, fark ve simetrik
fark gibi matematiksel işlemleri de destekler.

Küme oluşturmak için küme parantezleri veya "set()" fonksiyonu
kullanılabilir.  Not: boş bir küme oluşturmak için "{}" değil "set()"
kullanmanız gerekir, çünkü birincisi boş bir sözlük oluşturur, ki bu
da bir sonraki bölümde tartışacağımız bir veri yapısıdır.

İşte kısa bir gösterim:

   >>> basket = {'apple', 'orange', 'apple', 'pear', 'orange', 'banana'}
   >>> print(basket)                      # show that duplicates have been removed
   {'orange', 'banana', 'pear', 'apple'}
   >>> 'orange' in basket                 # fast membership testing
   True
   >>> 'crabgrass' in basket
   False

   >>> # Demonstrate set operations on unique letters from two words
   ...
   >>> a = set('abracadabra')
   >>> b = set('alacazam')
   >>> a                                  # unique letters in a
   {'a', 'r', 'b', 'c', 'd'}
   >>> a - b                              # letters in a but not in b
   {'r', 'd', 'b'}
   >>> a | b                              # letters in a or b or both
   {'a', 'c', 'r', 'd', 'b', 'm', 'z', 'l'}
   >>> a & b                              # letters in both a and b
   {'a', 'c'}
   >>> a ^ b                              # letters in a or b but not both
   {'r', 'd', 'b', 'm', 'z', 'l'}

liste kavramaları gibi küme kavramaları da desteklenmektedir:

   >>> a = {x for x in 'abracadabra' if x not in 'abc'}
   >>> a
   {'r', 'd'}


5.5. Sözlükler
==============

Another useful data type built into Python is the *dictionary* (see
Mapping Types --- dict). Dictionaries are sometimes found in other
languages as "associative memories" or "associative arrays".  Unlike
sequences, which are indexed by a range of numbers, dictionaries are
indexed by *keys*, which can be any immutable type; strings and
numbers can always be keys.  Tuples can be used as keys if they
contain only strings, numbers, or tuples; if a tuple contains any
mutable object either directly or indirectly, it cannot be used as a
key. You can't use lists as keys, since lists can be modified in place
using index assignments, slice assignments, or methods like "append()"
and "extend()".

Bir sözlüğü *anahtar: değer* çiftleri olarak düşünmek en iyisidir. Bir
sözlük içerisindeki her anahtarın benzersiz olması gerektiğini ise
unutmayın. Bir çift parantez boş bir sözlük oluşturur: "{}".
Anahtar:değer çiftlerinin virgülle ayrılmış bir listesini parantezler
içine yerleştirmek sözlüğe ilk anahtar:değer çiftlerini ekler;
sözlükler çıktıda da aynı bu şekilde görünürler.

Bir sözlük üzerindeki ana işlemler, bir değeri bir anahtarla depolamak
ve anahtarı verilen değeri geri çıkarmaktır.  Ayrıca "del" ile bir
anahtar:değer çiftini silmek de mümkündür. Zaten bir değeri kullanımda
olan bir anahtar kullanarak saklarsanız, bu anahtarla ilişkili eski
değer unutulur.  Var olmayan bir anahtar kullanarak değer çıkarmak bir
hatadır.

Bir sözlük üzerinde "list(d)" işlemini gerçekleştirmek, sözlükte
kullanılan tüm anahtarların bir listesini eklenme sırasına göre
döndürür (başka bir düzenle sıralanmasını istiyorsanız, bunun yerine
"sorted(d)" kullanın). Tek bir anahtarın sözlükte olup olmadığını
kontrol etmek için "in" anahtar sözcüğünü kullanın.

İşte sözlük kullanılan bir örnek:

   >>> tel = {'jack': 4098, 'sape': 4139}
   >>> tel['guido'] = 4127
   >>> tel
   {'jack': 4098, 'sape': 4139, 'guido': 4127}
   >>> tel['jack']
   4098
   >>> del tel['sape']
   >>> tel['irv'] = 4127
   >>> tel
   {'jack': 4098, 'guido': 4127, 'irv': 4127}
   >>> list(tel)
   ['jack', 'guido', 'irv']
   >>> sorted(tel)
   ['guido', 'irv', 'jack']
   >>> 'guido' in tel
   True
   >>> 'jack' not in tel
   False

"dict()" yapıcısı, doğrudan anahtar-değer dizilerinden sözlükler
oluşturur:

   >>> dict([('sape', 4139), ('guido', 4127), ('jack', 4098)])
   {'sape': 4139, 'guido': 4127, 'jack': 4098}

Buna ek olarak, sözlük kavramaları rastgele anahtar ve değer
ifadelerinden sözlükler oluşturmak için de kullanılabilir:

   >>> {x: x**2 for x in (2, 4, 6)}
   {2: 4, 4: 16, 6: 36}

Anahtarlar basit dizgiler olduğunda, anahtar sözcük argümanlarını
kullanarak çiftleri belirtmek bazen daha kolaydır:

   >>> dict(sape=4139, guido=4127, jack=4098)
   {'sape': 4139, 'guido': 4127, 'jack': 4098}


5.6. Döngü Teknikleri
=====================

When looping through dictionaries, the key and corresponding value can
be retrieved at the same time using the "items()" method.

   >>> knights = {'gallahad': 'the pure', 'robin': 'the brave'}
   >>> for k, v in knights.items():
   ...     print(k, v)
   ...
   gallahad the pure
   robin the brave

Bir dizi boyunca döngü yaparken, "enumerate()" fonksiyonu kullanılarak
konum indeksi ve karşılık gelen değer aynı anda alınabilir.

   >>> for i, v in enumerate(['tic', 'tac', 'toe']):
   ...     print(i, v)
   ...
   0 tic
   1 tac
   2 toe

Aynı anda iki veya daha fazla dizi üzerinde döngü yapmak için,
girdiler "zip()" fonksiyonu ile eşleştirilebilir.

   >>> questions = ['name', 'quest', 'favorite color']
   >>> answers = ['lancelot', 'the holy grail', 'blue']
   >>> for q, a in zip(questions, answers):
   ...     print('What is your {0}?  It is {1}.'.format(q, a))
   ...
   What is your name?  It is lancelot.
   What is your quest?  It is the holy grail.
   What is your favorite color?  It is blue.

Bir dizi üzerinde ters yönde döngü yapmak için, önce diziyi ileri
yönde belirtin ve ardından "reversed()" fonksiyonunu çağırın.

   >>> for i in reversed(range(1, 10, 2)):
   ...     print(i)
   ...
   9
   7
   5
   3
   1

Bir dizi üzerinde sıralı olarak döngü yapmak için, listenin kaynağını
değiştirmeksizin yeni bir sıralı liste döndüren "sorted()"
fonksiyonunu kullanın.

   >>> basket = ['apple', 'orange', 'apple', 'pear', 'orange', 'banana']
   >>> for i in sorted(basket):
   ...     print(i)
   ...
   apple
   apple
   banana
   orange
   orange
   pear

Bir dizi üzerinde "set()" kullanmak yinelenen öğeleri ortadan
kaldırır. Bir dizi üzerinde "set()" ile birlikte "sorted()" kullanımı,
dizinin benzersiz öğeleri üzerinde sıralı olarak döngü oluşturmanın
deyimsel bir yoludur.

   >>> basket = ['apple', 'orange', 'apple', 'pear', 'orange', 'banana']
   >>> for f in sorted(set(basket)):
   ...     print(f)
   ...
   apple
   banana
   orange
   pear

Bazen bir liste üzerinde döngü yaparken değiştirmek cazip gelebilir;
ancak bunun yerine yeni bir liste oluşturmak genellikle daha basit ve
daha güvenlidir.

   >>> import math
   >>> raw_data = [56.2, float('NaN'), 51.7, 55.3, 52.5, float('NaN'), 47.8]
   >>> filtered_data = []
   >>> for value in raw_data:
   ...     if not math.isnan(value):
   ...         filtered_data.append(value)
   ...
   >>> filtered_data
   [56.2, 51.7, 55.3, 52.5, 47.8]


5.7. Koşullar Üzerine
=====================

"while" ve "if" deyimlerinde kullanılan koşullar sadece karşılaştırma
değil, herhangi bir operatör içerebilir.

Karşılaştırma operatörleri "in" ve "not in" bir değerin bir dizide
olup olmadığını kontrol eder.  "is" ve "is not" operatörleri iki
nesnenin gerçekten aynı nesne olup olmadığını karşılaştırır.  Tüm
karşılaştırma operatörleri aynı önceliğe sahiptir, bu öncelik ise tüm
sayısal operatörlerden daha düşüktür.

Karşılaştırmalar art arda zincirlenebilir.  Örneğin, "a < b == c"
ifadesi "a" değerinin "b" değerinden küçük olup olmadığını test
ederken aynı zamanda "b" değerinin "c" değerine eşit olup olmadığını
test eder.

Karşılaştırmalar "and" ve "or" Boolean operatörleri kullanılarak
birleştirilebilir ve bir karşılaştırmanın (veya başka bir Boolean
ifadesinin) sonucu "not" ile olumsuzlanabilir.  Bunlar karşılaştırma
operatörlerinden daha düşük önceliklere sahiptir; aralarında, "not" en
yüksek önceliğe ve "or" en düşük önceliğe sahiptir, böylece "A ve B
değil veya C", "(A ve (B değil)) veya C" ile eş değerdir. Her zaman
olduğu gibi, istenen bileşimi ifade etmek için parantezler
kullanılabilir.

Boolean operatörleri "and" ve "or" *kısa devre* operatörleri olarak
adlandırılır: argümanları soldan sağa doğru değerlendirilir ve sonuç
belirlenir belirlenmez değerlendirme durur.  Örneğin, "A" ve "C" doğru
ancak "B" yanlış ise, "A ve B ve C" "C" ifadesini değerlendirmez.
Boolean olarak değil de genel bir değer olarak kullanıldığında, kısa
devre işlecinin dönüş değeri son değerlendirilen bağımsız değişkendir.

Bir değişkene, bir karşılaştırmanın sonucunu veya başka bir Boolean
ifadesini atamak mümkündür. Örneğin:

   >>> string1, string2, string3 = '', 'Trondheim', 'Hammer Dance'
   >>> non_null = string1 or string2 or string3
   >>> non_null
   'Trondheim'

Python'da, C'den farklı olarak, ifadelerin içindeki atamanın walrus
operatörü "=" ile açıkça yapılması gerektiğini unutmayın. Bu, C
programlarında karşılaşılan yaygın bir sorunu önler: "==" yazmak
isterken "=" yazmak.


5.8. Diziler ile Diğer Veri Tiplerinin Karşılaştırılması
========================================================

Dizi nesneleri tipik olarak aynı dizi türüne sahip diğer nesnelerle
karşılaştırılabilir. Karşılaştırmada *sözlüksel* sıralama kullanılır:
önce ilk iki öğe karşılaştırılır ve farklılarsa bu karşılaştırmanın
sonucunu belirler; eşitlerse, sonraki iki öğe karşılaştırılır ve her
iki dizi de tükenene kadar böyle devam eder. Karşılaştırılacak iki
öğenin kendileri de aynı türden diziler ise, sözlükbilimsel
karşılaştırma özyinelemeli olarak gerçekleştirilir.  İki dizinin tüm
öğeleri eşit çıkarsa, diziler eşit kabul edilir. Eğer dizilerden biri
diğerinin alt dizisi ise, daha kısa olan dizi daha küçük (küçük)
olandır.  Dizgiler için sözlükbilimsel sıralama, tek tek karakterleri
sıralamak için Unicode kod noktası numarasını kullanır. Aynı türdeki
diziler arasındaki karşılaştırmalara 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)

Nesnelerin uygun karşılaştırma yöntemlerine sahip olması koşuluyla,
farklı türlerdeki nesnelerin "<" veya ">" ile karşılaştırılabileceğini
unutmayın.  Örneğin, karışık sayısal türler sayısal değerlerine göre
karşılaştırılır, bu nedenle 0 eşittir 0.0, vb.  Bu türler uygun
yöntemlere sahip değillerse, yorumlayıcı rastgele bir sıralama
döndürmek yerine "TypeError" hatası verir.

-[ Dipnotlar ]-

[1] Diğer diller, "d->insert("a")->remove("b")->sort();" gibi yöntem
    zincirlemesine izin veren değiştirilmiş nesneyi döndürebilir.
