3. Python'a Resmi Olmayan Bir Giriş
***********************************

İlerleyen örneklerde; giriş ve çıkış, bilgi istemlerinin olup
olmamasına göre ayırt edilir (*>>>* ve *...*): örneği tekrarlamak için
bilgi isteminden sonra her şeyi yazmalısınız, istem göründüğünde bir
bilgi istemi ile başlamayan satırlar yorumlayıcıdan çıkar. Bir örnekte
tek başına bir satırdaki ikincil istemin boş bir satır yazmanız
gerektiği anlamına geldiğini unutmayın; bu, çok satırlı bir komutu
sonlandırmak için kullanılır.

Bu kılavuzdaki örneklerin çoğu, etkileşimli komut isteminde girilenler
dahil, yorumlar içerir. Python'da yorumlar, "#" hash karakteriyle
başlar ve fiziksel satırın sonuna kadar uzanır. Bir satırın başında
veya boşluk veya kodun ardından bir yorum görünebilir, ancak bir dize
sabiti içinde değil. Bir dize sabiti içindeki bir hash karakteri,
yalnızca bir hash karakterdir. Yorumlar kodu netleştirmek için
olduğundan ve Python tarafından yorumlanmadığından örnekler yazarken
atlanabilirler.

Bazı örnekler:

   # this is the first comment
   spam = 1  # and this is the second comment
             # ... and now a third!
   text = "# This is not a comment because it's inside quotes."


3.1. Python'ı Hesap Makinesi Olarak Kullanmak
=============================================

Bazı basit Python komutlarını deneyelim. Yorumlayıcıyı başlatın ve
">>>" birincil istemini bekleyin. (Uzun sürmemelidir.)


3.1.1. Sayılar
--------------

Yorumlayıcı basit bir hesap makinesi görevi görür: ona bir ifade
yazabilirsiniz ve değeri yazacaktır. İfade sözdizimi basittir: "+",
"-", "*" ve "/" operatörleri, tıpkı diğer birçok dilde (örneğin,
Pascal veya C) olduğu gibi çalışır; gruplama için parantezler ("()")
kullanılabilir. Örneğin:

   >>> 2 + 2
   4
   >>> 50 - 5*6
   20
   >>> (50 - 5*6) / 4
   5.0
   >>> 8 / 5  # division always returns a floating point number
   1.6

Tam sayıların (örneğin "2", "4", "20") türü "int" olup, kesirli kısmı
olanlar (örneğin "5.0", "1.6") "float" türüne sahiptir.  Sayısal
türler hakkında sonrasında daha fazlasını göreceğiz.

Division ("/") always returns a float.  To do *floor division* and get
an integer result (discarding any fractional result) you can use the
"//" operator; to calculate the remainder you can use "%":

   >>> 17 / 3  # classic division returns a float
   5.666666666666667
   >>>
   >>> 17 // 3  # floor division discards the fractional part
   5
   >>> 17 % 3  # the % operator returns the remainder of the division
   2
   >>> 5 * 3 + 2  # result * divisor + remainder
   17

Python ile üslü sayıları hesaplamak için "**" operatörünü kullanmak
mümkündür [1]:

   >>> 5 ** 2  # 5 squared
   25
   >>> 2 ** 7  # 2 to the power of 7
   128

Bir değişkene değer atamak için eşittir işareti ("=") kullanılır. Daha
sonra, bir sonraki etkileşimli komut isteminden önce hiçbir sonuç
görüntülenmez:

   >>> width = 20
   >>> height = 5 * 9
   >>> width * height
   900

Bir değişken "tanımlı" değilse (bir değer atanmamışsa), onu kullanmaya
çalışmak size bir hata verecektir:

   >>> n  # try to access an undefined variable
   Traceback (most recent call last):
     File "<stdin>", line 1, in <module>
   NameError: name 'n' is not defined

Ondalıklı sayı için tam destek var; karışık türde işlenenlere sahip
operatörler, tam sayı işlenenini ondalıklı sayıya dönüştürür:

   >>> 4 * 3.75 - 1
   14.0

Etkileşimli modda, son yazdırılan ifade "_" değişkenine atanır. Bu,
Python'ı bir masa hesap makinesi olarak kullandığınızda, hesaplamalara
devam etmenin biraz daha kolay olduğu anlamına gelir, örneğin:

   >>> tax = 12.5 / 100
   >>> price = 100.50
   >>> price * tax
   12.5625
   >>> price + _
   113.0625
   >>> round(_, 2)
   113.06

Bu değişken, kullanıcı tarafından salt okunur olarak ele alınmalıdır.
Açıkça ona bir değer atamayın --- sihirli davranışları olan bu gömülü
değişkeni maskeleyen aynı ada sahip bağımsız bir yerel değişken
yaratırsınız.

"int" ve "float" 'a ek olarak Python, "Decimal" ve "Fraction" gibi
diğer sayı türlerini de destekler. Python ayrıca karmaşık sayılar için
gömülü desteğe sahiptir ve hayali kısmı belirtmek için "j" veya "J"
son ekini kullanır (ör. "3+5j").


3.1.2. Dizeler
--------------

Sayıların yanı sıra Python, çeşitli şekillerde ifade edilebilen
dizeleri de değiştirebilir. Tek tırnak ("'...'") veya çift tırnak
(""..."") içine alınabilirler ve aynı sonuç olur [2]. "\" tırnaklardan
kaçmak için kullanılabilir:

   >>> 'spam eggs'  # single quotes
   'spam eggs'
   >>> 'doesn\'t'  # use \' to escape the single quote...
   "doesn't"
   >>> "doesn't"  # ...or use double quotes instead
   "doesn't"
   >>> '"Yes," they said.'
   '"Yes," they said.'
   >>> "\"Yes,\" they said."
   '"Yes," they said.'
   >>> '"Isn\'t," they said.'
   '"Isn\'t," they said.'

Etkileşimli yorumlayıcıda, çıktı dizesi tırnak işaretleri içine alınır
ve özel karakterler ters eğik çizgiyle çıkarılır. Bu bazen girdiden
farklı görünse de (ilgili tırnak işaretleri değişebilir), iki dize eş
değerdir. Dize tek bir tırnak işareti içeriyorsa ve çift tırnak
içermiyorsa dize çift tırnak içine alınır, aksi takdirde tek tırnak
içine alınır. "print()" fonksiyonu, ekteki tırnak işaretlerini
atlayarak ve çıkış karakterlerini ve özel karakterleri yazdırarak daha
okunaklı bir çıktı üretir:

   >>> '"Isn\'t," they said.'
   '"Isn\'t," they said.'
   >>> print('"Isn\'t," they said.')
   "Isn't," they said.
   >>> s = 'First line.\nSecond line.'  # \n means newline
   >>> s  # without print(), \n is included in the output
   'First line.\nSecond line.'
   >>> print(s)  # with print(), \n produces a new line
   First line.
   Second line.

"\" ile başlayan karakterlerin özel karakterler olarak yorumlanmasını
istemiyorsanız, ilk alıntıdan önce bir "r" ekleyerek *ham dizeleri
(raw strings)* kullanabilirsiniz:

   >>> print('C:\some\name')  # here \n means newline!
   C:\some
   ame
   >>> print(r'C:\some\name')  # note the r before the quote
   C:\some\name

Dize sabitleri birden çok satıra yayılabilir. Bunun bir yolu üçlü
tırnak kullanmaktır: """"..."""" veya "'''...'''". Satır sonu otomatik
olarak dizeye dahil edilir, ancak satırın sonuna "\" ekleyerek bunu
önlemek mümkündür. Aşağıdaki örnek:

   print("""\
   Usage: thingy [OPTIONS]
        -h                        Display this usage message
        -H hostname               Hostname to connect to
   """)

aşağıdaki çıktıyı üretir (ilk yeni satırın dahil olmadığını
unutmayın):

   Usage: thingy [OPTIONS]
        -h                        Display this usage message
        -H hostname               Hostname to connect to

Dizeler "+" operatörüyle birleştirilebilir (birbirine
yapıştırılabilir) ve "*" ile tekrarlanabilir:

   >>> # 3 times 'un', followed by 'ium'
   >>> 3 * 'un' + 'ium'
   'unununium'

Yan yana iki veya daha fazla *dize sabiti* (yani, tırnak işaretleri
arasına alınanlar) otomatik olarak birleştirilir.

   >>> 'Py' 'thon'
   'Python'

Bu özellik, özellikle uzun dizeleri kırmak istediğinizde
kullanışlıdır:

   >>> text = ('Put several strings within parentheses '
   ...         'to have them joined together.')
   >>> text
   'Put several strings within parentheses to have them joined together.'

Bu, değişkenler veya ifadelerle değil, yalnızca iki sabit değerle
çalışır:

   >>> prefix = 'Py'
   >>> prefix 'thon'  # can't concatenate a variable and a string literal
     File "<stdin>", line 1
       prefix 'thon'
                   ^
   SyntaxError: invalid syntax
   >>> ('un' * 3) 'ium'
     File "<stdin>", line 1
       ('un' * 3) 'ium'
                      ^
   SyntaxError: invalid syntax

Değişkenleri veya bir değişkeni ve bir sabiti birleştirmek
istiyorsanız, "+" kullanın:

   >>> prefix + 'thon'
   'Python'

Dizeler, ilk karakterin indeksi 0 olacak şekilde *dizine eklenebilir*
(abone olabilir). Karakterler için ayrı bir tür yoktur; karakterler
yalnızca *bir* uzunluğunda dizelerdir:

   >>> word = 'Python'
   >>> word[0]  # character in position 0
   'P'
   >>> word[5]  # character in position 5
   'n'

Sağdan saymaya başlamak için indeksler negatif sayılar da olabilir:

   >>> word[-1]  # last character
   'n'
   >>> word[-2]  # second-last character
   'o'
   >>> word[-6]
   'P'

-0 ile 0 aynı olduğundan, negatif endekslerin -1'den başladığını
unutmayın.

İndekslemeye ek olarak *dilimleme* de desteklenir. Tek tek
karakterleri elde etmek için indeksleme kullanılırken, *dilimleme* alt
dizeyi elde etmenizi sağlar:

   >>> word[0:2]  # characters from position 0 (included) to 2 (excluded)
   'Py'
   >>> word[2:5]  # characters from position 2 (included) to 5 (excluded)
   'tho'

Başlangıcın her zaman dahil edildiğine ve sonun her zaman hariç
tutulduğuna dikkat edin. Bu, "s[:i] + s[i:]" değerinin her zaman "s"
değerine eşit olmasını sağlar:

   >>> word[:2] + word[2:]
   'Python'
   >>> word[:4] + word[4:]
   'Python'

Dilim indekslerinin kullanışlı varsayılanları vardır; atlanmış bir ilk
dizin varsayılanı sıfırdır, atlanmış bir ikinci dizin varsayılanı
dilimlenmekte olan dizenin boyutudur.

   >>> word[:2]   # character from the beginning to position 2 (excluded)
   'Py'
   >>> word[4:]   # characters from position 4 (included) to the end
   'on'
   >>> word[-2:]  # characters from the second-last (included) to the end
   'on'

Dilimlerin nasıl çalıştığını hatırlamanın bir yolu, dizinleri ilk
karakterin sol kenarı 0 ile *arasındaki* karakterleri işaret ediyor
olarak düşünmektir. Ardından, *n* karakterli bir dizenin son
karakterinin sağ kenarında *n* dizini vardır, örneğin:

    +---+---+---+---+---+---+
    | P | y | t | h | o | n |
    +---+---+---+---+---+---+
    0   1   2   3   4   5   6
   -6  -5  -4  -3  -2  -1

İlk sayı satırı, dizideki 0...6 endekslerinin konumunu verir; ikinci
satır, karşılık gelen negatif endeksleri verir. *i* ile *j* arasındaki
dilim, sırasıyla *i* ve *j* etiketli kenarlar arasındaki tüm
karakterlerden oluşur.

Negatif olmayan indeksler için, her ikisi de sınırlar içindeyse, bir
dilimin uzunluğu indekslerin farkıdır. Örneğin, "kelime[1:3]" 'ün
uzunluğu 2'dir.

Çok büyük bir dizin kullanmaya çalışmak bir hataya neden olur:

   >>> word[42]  # the word only has 6 characters
   Traceback (most recent call last):
     File "<stdin>", line 1, in <module>
   IndexError: string index out of range

Ancak, aralık dışı dilim endeksleri, dilimleme için kullanıldığında
zarif bir şekilde işlenir:

   >>> word[4:42]
   'on'
   >>> word[42:]
   ''

Python dizeleri değiştirilemez --- bunlar *immutable* 'dır. Bu
nedenle, dizide dizine alınmış bir konuma atamak bir hatayla
sonuçlanır:

   >>> word[0] = 'J'
   Traceback (most recent call last):
     File "<stdin>", line 1, in <module>
   TypeError: 'str' object does not support item assignment
   >>> word[2:] = 'py'
   Traceback (most recent call last):
     File "<stdin>", line 1, in <module>
   TypeError: 'str' object does not support item assignment

Farklı bir dizeye ihtiyacınız varsa, yeni bir tane oluşturmalısınız:

   >>> 'J' + word[1:]
   'Jython'
   >>> word[:2] + 'py'
   'Pypy'

Yerleşik işlev "len()", bir dizenin uzunluğunu döndürür:

   >>> s = 'supercalifragilisticexpialidocious'
   >>> len(s)
   34

Ayrıca bkz.:

  Metin Sırası Türü --- str
     Dizeler, *sıra türlerinin* örnekleridir ve bu türler tarafından
     desteklenen genel işlemleri destekler.

  String (Dize) Metotları
     Dizeler, temel dönüşümler ve arama için çok sayıda yöntemi
     destekler.

  Formatted string literals
     Gömülü ifadelere sahip dize sabitleri.

  Format String Syntax
     "str.format()" ile dize biçimlendirme hakkında bilgi.

  printf-style String Formatting
     Dizeler "%" operatörünün sol işleneni olduğunda çağrılan eski
     biçimlendirme işlemleri burada daha ayrıntılı olarak
     açıklanmaktadır.


3.1.3. Listeler
---------------

Python, diğer değerleri gruplamak için kullanılan bir dizi *bileşik*
veri türünü bilir. En çok yönlü olanı, köşeli parantezler arasında
virgülle ayrılmış değerlerin (ögelerin) bir listesi olarak yazılabilen
*liste*'dir. Listeler farklı türde ögeler içerebilir, ancak genellikle
ögelerin tümü aynı türdedir.

   >>> squares = [1, 4, 9, 16, 25]
   >>> squares
   [1, 4, 9, 16, 25]

Dizeler gibi (ve diğer tüm yerleşik *sequence* türleri), listeler
dizine alınabilir ve dilimlenebilir:

   >>> squares[0]  # indexing returns the item
   1
   >>> squares[-1]
   25
   >>> squares[-3:]  # slicing returns a new list
   [9, 16, 25]

Tüm dilim işlemleri, istenen ögeleri içeren yeni bir liste döndürür.
Bu, aşağıdaki dilimin listenin bir shallow copy döndürdüğü anlamına
gelir:

   >>> squares[:]
   [1, 4, 9, 16, 25]

Ayrıca listeler birleştirme gibi işlemleri de destekler:

   >>> squares + [36, 49, 64, 81, 100]
   [1, 4, 9, 16, 25, 36, 49, 64, 81, 100]

*immutable* olan dizelerin aksine, listeler *mutable* türündedir, yani
içeriklerini değiştirmek mümkündür:

   >>> cubes = [1, 8, 27, 65, 125]  # something's wrong here
   >>> 4 ** 3  # the cube of 4 is 64, not 65!
   64
   >>> cubes[3] = 64  # replace the wrong value
   >>> cubes
   [1, 8, 27, 64, 125]

Ayrıca, "append()" *method*'u kullanarak listenin sonuna yeni öğeler
ekleyebilirsiniz (yöntemler hakkında daha fazla bilgiyi daha sonra
göreceğiz):

   >>> cubes.append(216)  # add the cube of 6
   >>> cubes.append(7 ** 3)  # and the cube of 7
   >>> cubes
   [1, 8, 27, 64, 125, 216, 343]

Dilimlere atama da mümkündür ve bu, listenin boyutunu bile
değiştirebilir veya tamamen temizleyebilir:

   >>> letters = ['a', 'b', 'c', 'd', 'e', 'f', 'g']
   >>> letters
   ['a', 'b', 'c', 'd', 'e', 'f', 'g']
   >>> # replace some values
   >>> letters[2:5] = ['C', 'D', 'E']
   >>> letters
   ['a', 'b', 'C', 'D', 'E', 'f', 'g']
   >>> # now remove them
   >>> letters[2:5] = []
   >>> letters
   ['a', 'b', 'f', 'g']
   >>> # clear the list by replacing all the elements with an empty list
   >>> letters[:] = []
   >>> letters
   []

Yerleşik işlev "len()" ayrıca listeler için de geçerlidir:

   >>> letters = ['a', 'b', 'c', 'd']
   >>> len(letters)
   4

Listeleri iç içe yerleştirmek (diğer listeleri içeren listeler
oluşturmak) mümkündür, örneğin:

   >>> a = ['a', 'b', 'c']
   >>> n = [1, 2, 3]
   >>> x = [a, n]
   >>> x
   [['a', 'b', 'c'], [1, 2, 3]]
   >>> x[0]
   ['a', 'b', 'c']
   >>> x[0][1]
   'b'


3.2. Programlamaya Doğru İlk Adımlar
====================================

Elbette Python'ı iki ile ikiyi toplamaktan daha komplike görevler için
kullanabiliriz. Örneğin, Fibonacci serisinin ilk alt dizisini
aşağıdaki gibi yazabiliriz:

   >>> # Fibonacci series:
   ... # the sum of two elements defines the next
   ... a, b = 0, 1
   >>> while a < 10:
   ...     print(a)
   ...     a, b = b, a+b
   ...
   0
   1
   1
   2
   3
   5
   8

Bu örnek, birkaç yeni özellik sunar.

* İlk satır bir *çoklu atama*: "a" ve "b" değişkenleri aynı anda yeni
  0 ve 1 değerlerini alır. Tarafların tümü, herhangi bir görev
  yapılmadan önce değerlendirilir. Sağ taraftaki ifadeler soldan sağa
  doğru değerlendirilir.

* "while" döngüsü, koşul (burada: "a < 10") doğru kaldığı sürece
  yürütülür. Python'da, C'de olduğu gibi, sıfır olmayan herhangi bir
  tam sayı değeri doğrudur; sıfır yanlıştır. Koşul ayrıca bir dizi
  veya liste değeri, aslında herhangi bir dizi olabilir; uzunluğu
  sıfır olmayan her şey doğrudur, boş diziler yanlıştır. Örnekte
  kullanılan test basit bir karşılaştırmadır. Standart karşılaştırma
  işleçleri C'dekiyle aynı şekilde yazılır: "<" (küçüktür), ">"
  (büyüktür), "==" (eşittir), "<=" ( küçük veya eşit), ">=" (büyük
  veya eşit) ve "!=" (eşit değil).

* Döngünün *gövdesi girintilidir*: girinti, Python'un ifadeleri
  gruplama şeklidir. Etkileşimli komut isteminde, girintili her satır
  için bir sekme veya boşluk(lar) yazmanız gerekir. Pratikte, bir
  metin düzenleyici ile Python için daha karmaşık girdiler
  hazırlayacaksınız; tüm düzgün metin editörlerinin otomatik girinti
  özelliği vardır. Bir bileşik deyim etkileşimli olarak girildiğinde,
  tamamlandığını belirtmek için boş bir satırdan sonra gelmelidir
  (çünkü ayrıştırıcı son satırı ne zaman yazdığınızı tahmin edemez).
  Bir temel blok içindeki her satırın aynı miktarda girintili olması
  gerektiğini unutmayın.

* "print()" işlevi, kendisine verilen argüman(lar)ın değerini yazar.
  Yalnızca yazmak istediğiniz ifadeyi yazmaktan (daha önce hesap
  makinesi örneklerinde yaptığımız gibi) birden çok bağımsız
  değişkeni, kayan nokta miktarlarını ve dizeleri işleme biçiminden
  farklıdır. Dizeler tırnak işaretleri olmadan yazdırılır ve öğelerin
  arasına bir boşluk eklenir, böylece şunları güzel bir şekilde
  biçimlendirebilirsiniz:

     >>> i = 256*256
     >>> print('The value of i is', i)
     The value of i is 65536

  *end* anahtar sözcüğü argümanı, çıktıdan sonra yeni satırı önlemek
  veya çıktıyı farklı bir dizeyle bitirmek için kullanılabilir:

     >>> a, b = 0, 1
     >>> while a < 1000:
     ...     print(a, end=',')
     ...     a, b = b, a+b
     ...
     0,1,1,2,3,5,8,13,21,34,55,89,144,233,377,610,987,

-[ Dipnotlar ]-

[1] "**", "-" 'den daha yüksek önceliğe sahip olduğundan, "-3**2",
    "-(3**2)" olarak yorumlanacak ve dolayısıyla "-9" ile
    sonuçlanacaktır. Bundan kaçınmak ve "9" elde etmek için "(-3)**2"
    kullanabilirsiniz.

[2] Diğer dillerden farklı olarak, "\n" gibi özel karakterler hem tek
    ("'...'") hem de çift (""..."") tırnak işaretleri ile aynı anlama
    sahiptir. İkisi arasındaki tek fark, tek tırnak içinde """ dan
    kaçmanıza gerek olmamasıdır (ancak "\'" dan kaçmanız gerekir) ve
    bunun tersi de geçerlidir.
