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
--------------

The interpreter acts as a simple calculator: you can type an
expression into it and it will write the value.  Expression syntax is
straightforward: the operators "+", "-", "*" and "/" can be used to
perform arithmetic; parentheses ("()") can be used for grouping. For
example:

   >>> 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.

Bölme ("/") her zaman bir ondalıklı sayı döndürür. *floor division*
yapmak ve bir tam sayı sonucu almak için "//" operatörünü
kullanabilirsiniz; kalanı hesaplamak içinse "%" operatörünü
kullanabilirsiniz:

   >>> 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  # floored quotient * 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. Metin
------------

Python sayıların yanı sıra metinleri de ("string" olarak adlandırılan
"str" türü ile temsil edilir) işleyebilir.  Bu karakterleri ""!"",
kelimeleri ""tavşan"", isimleri ""Paris"", cümleleri ""Arkanı
kolluyorum."", vb. içerir. ""Yay! :)"". Tek tırnak ("'...'") veya çift
tırnak (""..."") içine alınabilirler ve aynı sonucu verirler [2].

   >>> 'spam eggs'  # single quotes
   'spam eggs'
   >>> "Paris rabbit got your back :)! Yay!"  # double quotes
   'Paris rabbit got your back :)! Yay!'
   >>> '1975'  # digits and numerals enclosed in quotes are also strings
   '1975'

Bir alıntıyı alıntılamak için, önüne "\" koyarak "kaçmamız"(escape)
gerekir. Alternatif olarak, diğer tırnak işareti türlerini de
kullanabiliriz:

   >>> '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.'

Python kabuğunda(shell), string tanımı ve çıktı stringi farklı
görünebilir.  "print()" fonksiyonu, tırnak işaretlerini atlayarak ve
kaçan ve özel karakterleri yazdırarak daha okunabilir bir çıktı
üretir:

   >>> s = 'First line.\nSecond line.'  # \n means newline
   >>> s  # without print(), special characters are included in the string
   'First line.\nSecond line.'
   >>> print(s)  # with print(), special characters are interpreted, so \n produces 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:\this\name')  # here \t means tab, \n means newline
   C:      his
   ame
   >>> print(r'C:\this\name')  # note the r before the quote
   C:\this\name

Ham dizelerin ince bir yönü vardır: ham bir dize tek sayıda "\"
karakterle bitmeyebilir; daha fazla bilgi ve geçici çözümler için SSS
'e bakın.

String literals can span multiple lines.  One way is using triple-
quotes: """"..."""" or "'''...'''".  End-of-line characters are
automatically included in the string, but it's possible to prevent
this by adding a "\" at the end of the line.  In the following
example, the initial newline is not included:

   >>> print("""\
   ... Usage: thingy [OPTIONS]
   ...      -h                        Display this usage message
   ...      -H hostname               Hostname to connect to
   ... """)
   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.

In addition to indexing, *slicing* is also supported.  While indexing
is used to obtain individual characters, *slicing* allows you to
obtain a substring:

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

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'

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'

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 bakınız:

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

  dize-yöntemleri
     Dizeler, temel dönüşümler ve arama için çok sayıda yöntemi
     destekler.

  f-strings
     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]

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]

You can also add new items at the end of the list, by using the
"list.append()" *method* (we will see more about methods later):

   >>> 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]

Simple assignment in Python never copies data. When you assign a list
to a variable, the variable refers to the *existing list*. Any changes
you make to the list through one variable will be seen through all
other variables that refer to it.:

   >>> rgb = ["Red", "Green", "Blue"]
   >>> rgba = rgb
   >>> id(rgb) == id(rgba)  # they reference the same object
   True
   >>> rgba.append("Alph")
   >>> rgb
   ["Red", "Green", "Blue", "Alph"]

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:

   >>> correct_rgba = rgba[:]
   >>> correct_rgba[-1] = "Alpha"
   >>> correct_rgba
   ["Red", "Green", "Blue", "Alpha"]
   >>> rgba
   ["Red", "Green", "Blue", "Alph"]

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.

* The "print()" function writes the value of the argument(s) it is
  given. It differs from just writing the expression you want to write
  (as we did earlier in the calculator examples) in the way it handles
  multiple arguments, floating-point quantities, and strings.  Strings
  are printed without quotes, and a space is inserted between items,
  so you can format things nicely, like this:

     >>> 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.
