# Hoşgeldiniz!

## Derslik Sayfasına Hoşgeldiniz!

[Kerteriz Blog](https://kerteriz.net) altında yayınlanan veya yayınlanmayan tüm dallara ait dersleri bir çatı altında toplamak için güzel bir **ansiklopedi** oluşturmaya çalıştık. Umarız ki sizler için güzel ve faydalı bir araç olur.

{% hint style="info" %}
Sol taraftaki menüden istediğiniz konunun derslerine ulaşabilir ve rahatlıkla kullanabilirsiniz.
{% endhint %}


# Python

Bu sayfadan Python ve frameworkleri hakkında birçok ders içeriğine ücretsiz ulaşabilirsiniz.


# Python Giriş

En popüler programlama dillerinden biri olan Python derslerine giriş yapıyoruz

**"Merhaba Dünya",** artık an itibari ile Python programlama derslerine başlıyoruz. Bunun için ilk olarak Python nedir, nerelerde kullanılır, neden tercih etmeliyim gibi soruları cevaplandırarak eğitimimize başlayabiliriz.

## 1. Python Nedir?

Python, Guido van Rossum tarafından 1991 yılında yayınlanan oldukça popüler bir programlama dilidir. Teknik olarak bakıldığında Python, önce derlenen (compiled), ardından derlenmiş kodun üstünden yorumlanan (interpretered) bir dildir.

{% hint style="info" %}
Yazılan bir kodu başka bir programlama diline çevirdikten sonra çalıştıran ve koddaki hataları yakalayan, kodun iyileştirilmesini daha kod çalıştırmadan yapan çeviricilere **derleyici (compiler)**, kodu satır satır veya bloklar halinde çalıştırıp sırası gelmeyen satırları hiç çalıştırmayan, sırası gelmeyen satırlardaki hataları göremeyen ve kodun bütününe ait iyileştirmeleri yapamayan çeviricilere de **yorumlayıcı (interpreter)** adı verilmektedir. Detaylı bilgi için [bakınız.](https://techdifferences.com/difference-between-compiler-and-interpreter.html)
{% endhint %}

## 2. Python İle Neler Yapılabilir?

* Python ile sunucu tabanlı web uygulamaları geliştirebilirsiniz.
* Python ile masaüstü programları geliştirebilirsiniz.
* Python ile projelerinizde ki veritabanı işlemlerinizi rahatlıkla yapabilirsiniz.
* Python ile büyük veri (big data) ve karışık matematiksel işlemler gibi veri analizi ve bilimsel faaliyetler üzerinde çalışabilirsiniz.
* Python ile Makine Öğrenimi, Yapay Zeka, Görüntü İşleme alanlarında uygulamalar yazabilir, bu alanlarda çalışabilirsiniz.
* Python ile örümcek tarzı yazılımlar geliştirebilirsiniz.
* Python ile ağ ve soket programcılığı üzerinde çalışmalar yapabilirsiniz.

## 3. Neden Python Kullanmalıyım?

Gerek popülerliği, gerek kolaylığı ve gerekse modülerliği sayesinde Python'a hızlı bir giriş yapabilir, neredeyse tüm yazılım ihtiyaçlarınızı hızlıca karşılayabilirsiniz. Tabi bu ve bunun gibi nedenlerden bazılarını sıralarsak şöyle bir liste elde etmiş oluruz;

* Python birçok farklı platformda çalışabilir (Windows, Linux, Mac, Rasperry Pi vs)
* Konuşma diline (İngilizce) çok yakındır ve syntax oldukça basittir. Kod yazarken rahat edebilirsiniz.
* Kodunuzu yazabilmeniz için öncesinde birçok kütüphane, sınıf vs. gereklilere ihtiyaç duymaz. Aklınızdaki algoritmayı sadece birkaç satır komutla bile hayata geçirebilirsiniz.
* Nesne tabanlı programla desteği vardır ve büyük projelerde profesyonelce kullanabilirsiniz.
* İnternet ve yazılı kaynaklarda çok fazla dökümanı mevcuttur ve ihtiyaç duyduğunuzda yardım edecek birilerini rahatlıkla bulabilirsiniz.

{% hint style="success" %}
Stackoverflow 2019 en popüler programlama dilleri anketinde birçok programlama dilinden daha yüksek bir konumda yer almıştır. İlgili haber için [tıklayınız.](https://webrazzi.com/2019/04/11/stack-overflow-2019-anketi-en-populer-programlama-dilleri/)
{% endhint %}

## 4. Bilmeniz Gerekenler

Derslerimize başlamadan önce belirtmeliyiz ki bu eğitim süreci boyunca en güncel versiyon olan **Python 3** ile anlatımlarımızı yapacağız. Ayrıca metin editörü olarak **Visual Studio Code** kullanmanızı tavsiye ediyoruz. Sizde aşağıdaki bağlantıları kullanarak ilgili dosyaları edinebilirsiniz.

> Python 3 indirmek için [Tıklayınız](https://www.python.org/downloads/)

> Visual Studio Code indirmek için [Tıklayınız](https://code.visualstudio.com)


# ⚙️ Python Kurulumu

Bu derste Python programlama dilini yazabilmek için bilgisayarınıza gerekli dosyaları nasıl kurabileceğinizi anlatıyoruz.

Python üzerine küçük bir giriş yaptıktan sonra Python öğrenmek isteyenlerle derslerimize devam ediyoruz. Bu dersimizde kod yazabilmek için hangi dosyaları kurmamız gerekiyor, hangi bileşenleri eklememiz gerekiyor anlatacağız. Öyleyse başlayalım.

## 1. Python Kurulumu

En güncel sürüm olan Python 3.x versiyonunu bilgisayarımıza kurabilmemiz için öncelikle aşağıdaki dosyayı bilgisayarınıza indiriniz.

> Python 3 indirmek için [Tıklayınız](https://www.python.org/downloads/)

Ardından indirdiğiniz dosyayı çalıştırınız ve kurulum aşamalarını ilerleterek programı bilgisayarınıza kurunuz.

{% hint style="warning" %}
Kurulumun ilk aşamasında yer alan **"Add Python 3.x to PATH"** kutucuğunu işaretleyiniz. Bu işaretlemeyi unuttuysanız manuel olarak path ekleme işini yapabilmek için [Tıklayınız. ](https://kerteriz.net/komut-satirinda-cmd-pyton-calistirma/)
{% endhint %}

{% hint style="info" %}
Kurulum aşamalarından olan **"Optional Features"** sayfasındaki tüm seçenekleri işaretlemenizi öneriyoruz.
{% endhint %}

Kurulum tamamlandığında artık Python komutlarımızı bilgisayarımızda yazabilir ve test edebilir hale gelmiş bulunuyoruz. Artık bir sonraki aşamaya geçebiliriz.

{% hint style="info" %}
Bilgisayarınıza kurulan Python sürümünü öğrenmek için **Komut İstemi** üzerinden (Windows > Komut İstemi) **python --version** komutunu çalıştırabilirsiniz.
{% endhint %}

{% tabs %}
{% tab title="Komut" %}

```python
python --version
```

{% endtab %}

{% tab title="Çıktı" %}

```
# Python 3.7.1
```

{% endtab %}
{% endtabs %}

## 2. İlk Python Kodumuzu Yazma ve Çalıştırma

Python ortamını kurduktan sonra ilk kodumuzu yazabilmek için istediğiniz bir klasörde **ilkkod.py** isimli bir dosya oluşturunuz ve Visual Studio Code ile açınız.

{% hint style="info" %}
Dosyayı **.py** uzantılı kaydedebilmek için Windows pencerelerde **Görünüm** sekmesi altında yer alan **"Dosya adı uzantıları"** kutucuğunu işaretleyiniz ve ilgili dosya ismini .py uzantılı olarak düzenleyiniz.
{% endhint %}

{% hint style="info" %}
Eğer bilgisayarınızda *Visual Studio Code* kurulu değilse bunun yerine *Atom* , *Not Defteri* , *Notepad++* gibi istediğiniz herhangi bir metin editörünü kullanabilirsiniz.
{% endhint %}

Ardından metin editörünüz ile açtığınız dosyaya aşağıdaki kodu yazınız ve kaydediniz.

```python
print("Kerteriz Blog ile Python öğreniyorum!")
```

Sırada komut istemi üzerinden ilkkod.py isimli dosyanızın bulunduğu dizini (`C:\Users\ismet\Desktop\ilkders>`) açınız ve aşağıdaki komutu çalıştırınız:

{% hint style="info" %}
**.py** dosyanızın olduğu dizin eğer masaüstünde **ilkders** isimli klasördeyse cmd üzerinden komutuyla ilgili klasöre gidebilirsiniz.
{% endhint %}

{% hint style="info" %}
Komut istemi üzerinden ilgili dosyanızın olduğu klasöre **cd** komutu ile gidebilirsiniz. (Ör: cd Desktop) Veya bulunduğunuz klasördeki dizin isminin yazdığı yere **cmd** yazarak *Enter* tuşuna bastığınızda komut istemi otomatik olarak bu dizin içinde açılacaktır. Tıklayınız. cd komutu hakkında daha fazla bilgi almak için&#x20;
{% endhint %}

{% tabs %}
{% tab title="Komut" %}

```python
python ilkkod.py
```

{% endtab %}
{% endtabs %}

Ekranda ki çıktının şu şekilde olduğunu görebileceksiniz:

```python
Kerteriz Blog ile Python öğreniyorum!
```

:partying\_face: **Tebrikler!** İlk Python kodunuzu yazdınız ve çalıştırdınız :)

{% hint style="warning" %}
Bu aşamada **"** '**python' is not recognized as an internal or external command, operable program or batch file."** şeklinde bir hata alırsanız düzeltmek için [Tıklayınız.](https://kerteriz.net/komut-satirinda-cmd-pyton-calistirma/)
{% endhint %}

![1. İlk Python komutunun yazılması ve cmd üzerinde çalıştırılması](/files/-LtLsd9nDTHPoYb-oIsq)

## 3. (Alternatif) Python Kodlarını CMD Üzerinde Yazma ve Çalıştırma

Bir önceki başlıkta Python kodlarımızı yazabilmemiz için bir dosya oluşturduk ve komutlarımızı üzerine yazdık. Bunun yerine küçük denemeleriniz için direkt olarak **Komut İstemini** açabilir ve komutunu çalıştırarak Python kodlarınızı yazmaya başlayabilirsiniz.

```python
C:\Users\ismet\Desktop>python 
Python 3.7.1 (default, Dec 10 2018, 22:54:23) [MSC v.1915 64 bit (AMD64)] :: Anaconda, Inc. on win32 
Type "help", "copyright", "credits" or "license" for more information.
>>> print("Merhaba Dünya!")
Merhaba Dünya!
>>>
```

{% hint style="info" %}
Bu ekrandan çıkış yapabilmek için **Ctrl+Z** yi tuşlayarak veya **exit()** yazarak **Enter** tuşuna basabilirsiniz.
{% endhint %}


# ✏️ Python Syntax

Bu derste Python dilinin yazım kurallarını (syntax) göreceğiz.

Her programlama dilinde olduğu gibi Python da kendine has kod yazım kurallarına sahiptir. Kod yazmaya başlamadan önce bu kuralları öğrenmeniz gerektiğinden bu derste **Pyhon Sytnax** konusunu işliyoruz.

## 1. Satır Girintileri

Python ile kodlama yaparken girintiler yani boşluklar en önemli konulardan birisidir. Eğer if/else/for gibi bloklara girdiğinizde bir boşluk bırakmazsanız Python o blok içine girdiğinizi anlamaz. Normal bir kod yazımında komutlarınız sola dayalı ve boşluksuz olmalıdır:

```python
print("Merhaba")
```

*If/else* , *for* gibi yapılar kullanırken ise ilgili blokun içine girmek için Tab tuşu ile girinti oluşturmalısınız:&#x20;

{% tabs %}
{% tab title="Doğru Kullanım" %}

```python
if 5 > 2: 
    print("Beş büyüktür ikiden") 
else: 
    print("Beş ikiden büyük değildir!")
```

{% endtab %}

{% tab title="Yanlış Kullanım" %}

```python
if 5 > 2: 
print("Beş büyüktür ikiden") 
else: 
print("Beş ikiden büyük değildir!")
```

{% endtab %}
{% endtabs %}

## 2. Satır Sonları

Daha önce farklı programlama dilleri kullandıysanız satır sonlarının ile bitmesi gerektiğini bilirsiniz. Fakat Python kullanırken satır sonlarına herhangi bir karakter koymanıza gerek yoktur. Aşağıda bir örneğini görebilirsiniz:

```python
a = 5 
b = 10 
toplam = a + b 

print("Toplam: " + toplam)
```


# Temel Dersler

Python programlama dilindeki temel dersleri aşağıdaki başlıklardan sırasıyla takip edebilirsiniz.


# # Python Yorumlar

Python yorumlar (comments) konusunu işliyoruz.

Bir kod yazarken en önemli aşamalardan birisi de daha sonra aynı koda baktığınızda ne yazdığını anlayabilmeniz, okuyabilmenizdir. Bunun için programlama dillerinde **yorumlar (comments)** kullanılır. Python dili içinde yorumları nasıl kullanabileceğimizi gelin görelim.

## 1. Tek Satırlık Yorumlar

Tek satırlık yorumları daha kısa notlar için kullanabilirsiniz. Bunun için öncelikle (diyez) işaretini koymalı ve ardından yorumunuzu yazmalısınız. Örneklerini aşağıda görebilirsiniz:

```python
#Aşağıdaki kod ile ekranda çıktı gösterebiliriz

print("Kerteriz Blog ile profeyonel içerikler")
```

```python
# print("Bu komut yorumlandığı için çalışmayacaktır!")

isim = "İsmet" #Burası da bir yorum alanı
```

Gördüğünüz üzere **#** işaretini nereye koyarsanız o konumdan itibaren yorum alanınız başlamış olur. Öncesindeki kodlar işletilmeye devam eder.

## 2. Çok Satırlık Yorumlar

Bazı durumlarda birden fazla satırı yorum haline getirmek, uzun açıklamalar girmek isteyebilirsiniz. Bu durumda her satırın başına **#** koymaktansa (üç adet çift tırnak) işareti ile kendinize çok satırlı yorum alanı oluşturabilirsiniz.

```python
""" Merhaba arkadaşlar! 
Bu satırlar yorum satırlarıdır ve 
çalıştırılmaz""" 

print("Hello, World!")
```


# # Python Değişkenler

Python değişkenler (variables) konusunu işliyoruz.

Programlama dillerinde elinizde ki sayı, isim, liste gibi ögeleri tutarken değişkenlere ihtiyaç duyarsınız ve **değişkenler (variables)** programlamada en temel ögedir. Özetle değişkenler elinizde ki verileri depolamanızı mümkün kılar. Birçok programlama dilinde değişkenleri oluştururken verinin tipini *(sayı mı, karakter mi, dizi mi gibi)* değişken isimlerinin önüne getirdiğiniz belirteçlerle tanımlarsınız. Fakat Python ile oluşturduğunuz değişkenlerde hiçbir ön eke gerek duymazsınız.

```python
a = 5     #sayı tipinde değişken 
a = "5"   #karakter grubu (string) tipinde değişken
```

Örnekte gördüğünüz üzere herhangi bir *int, float string, char* gibi ön eke gerek duymadan değişkenlerimizi oluşturduk ve Python otomatik olarak veri tiplerini algıladı. Ayrıca string veya char değişken türlerini oluştururken (çift tırnak) veya (tek tırnak) kullanabilirsiniz.

```python
isim = "Kerteriz Blog" 
isim = 'Kerteriz Blog'
```

## 1. Değişken İsimlerini Seçerken Dikkat Edilmesi Gerekenler

Öncelikle değişken isimlerinizi oluştururken tuttuğunuz değerleri çağrıştıracak ve programlamanızın ilerleyen süreçlerinde ilgili değişkeni rahat hatırlayabileceğiniz değişken isimleri oluşturmaya dikkat ediniz.&#x20;

{% tabs %}
{% tab title="Doğru Kullanım" %}

```python
isim
_sayi
Top10
sehir_
```

{% endtab %}

{% tab title="Yanlış Kullanım" %}

```python
10kitap
indirim%
#yas
hayvan.
```

{% endtab %}
{% endtabs %}

## 2. Çoklu Değişken Değerleri Tanımlama

İlerleyen süreçlerde pratiklik kazandığınızda tek satırda birçok değişken oluşturma veya farklı değişkenlere aynı değeri atama ihtiyacı duyabilirsiniz. Bunun için aşağıdaki kullanımları baz alabilirsiniz.

```python
x, y, z = "Elma", "Armut", "Çilek"

print(x) #Elma 
print(y) #Armut 
print(z) #Çilek
```

```python
x = y = z = "Karpuz"

print(x) #Karpuz 
print(y) #Karpuz 
print(z) #Karpuz
```

## 3. Local ve Global Değişkenler

Bir değişkeni nerede tanımladığınız, programlamanın ilerleyen süreçlerinde bu değişkeni kullanıp kullanamayacağınızı belirler. Nasıl yani? Örneğin bir değişkeni fonksiyon içinde tanımladığınızda o değişkeni sadece ilgili fonksiyon içinde kullanabilirsiniz. Fakat fonksiyonun dışında tanımladığınız bir değişkeni herhangi bir fonksiyon içinde rahatlıkla kullanabilirsiniz. Hemen örnekleri görelim:

```python
x = "Lale"

def ornekFonksiyon():
  y = "Pırasa"

  print(x)  # Lale
  print(y)  # Pırasa

ornekFonksiyon()

print(x)  # Lale
print(y)  # !!Hata verir
```

Bu örnekte değişkeni fonksiyonun dışında tanımlandığı için **global** bir değişkendir ve istediğiniz her yerde kullanabilirsiniz. değişkeni ise fonksiyonun içinde tanımlandığı için **local** bir değişkendir ve sadece aynı fonksiyon içinde kullanılabilir.

{% hint style="info" %}
Bir fonksiyon içinde tanımlanan local değişkenin sadece o fonksiyon içinde kullanılabileceğini gördük. Fakat bu değişkenin başında **global** terimini kullandığınızda ilgili değişken artık local değil global hale gelir ve fonksiyon dışında da kullanılabilir.
{% endhint %}

```python
def ornekFonksiyon():
  global y = "Pırasa"

  print(y)  # Pırasa

ornekFonksiyon()

print(y)  # Pırasa
```

## 4. Değişkenleri Ekrana Yazdırma

Artık değişkenleri nasıl oluşturacağımızı öğrendikten sonra bu değişkenleri ekrana nasıl yazdırırız örnekler üzerinde görelim.

```python
sehir = "Ankara"
a = 5
b = "5"
c = 3

print(sehir)                # Ankara
print("Şehir: " + sehir)    # Şehir: Ankara
print(a + c)                # 8
print(a + b)                # !!Hata verir (sayı ve metin toplanamaz)
```

## 5. Kullanıcıdan Değişkene Atanacak Değer Alma

Her zaman değişkenlere değerleri siz atamazsınız. Bazı durumlarda da kullanıcılara isimlerini, yaşlarını vs. sorarak ekrana yazdıkları değerleri siz bir değere atarsınız. Bunun için kullanıcılardan nasıl bir değer alarak değişkene atayabileceğimizin örneğini görelim.

```python
yas = input("Kaç yaşındasınız: ") 

print(yas)
```

Bu örnekte kullanıcı ekrana hangi değeri girerse o değer **yas** isimli değişkene atanacaktır.


# # Python Veri Tipleri

Python veri tipleri (data types) konusunu işliyoruz.

Bir önceki dersimizde değişkenlerin ne olduğunu ve nasıl oluşturabileceğimizi öğrendik. Şimdi ise Python programlama dillerinde oluşturduğumuz değişkenlerin hangi tiplerde olabileceklerini göreceğiz.

## 1. Veri Tipi Çeşitleri

Programlamada kullanacağımız verinin tipi çok önemlidir. Çünkü örnek olarak bir muhasebe programında ondalık sayılar kullanmanız gerekirken bunun yerine sadece tam sayılar kullanırsanız büyük sorunlar yaşarsınız. Bunun için kullanabileceğiniz veri tiplerini en başta öğrenmeniz çok önemlidir. Kullanabileceğiniz veri tipleri şunlardır;

* **Metin tipleri:** `str`
* **Sayısal tipler:** `int` , `float` , `complex`
* **Dizi tipleri:** `list` , `tuple` , `range`
* **Adresleme tipleri:** `dict`
* **Küme tipleri:** `set` , `frozenset`
* **Mantıksal tipler:** `bool`
* **Binary tipler:** `bytes` , `bytearray` , `memoryview`

Aşağıdaki tabloda her bir veri tipe ait değişkeni nasıl oluşturacağımızı ve bu veri tiplerine ait örnekleri görebilirsiniz.

| Örnek                                   | Veri Tipi  |
| --------------------------------------- | ---------- |
| x = "Merhaba Dünya"                     | str        |
| x = 20                                  | int        |
| x = 20.5                                | float      |
| x = 1j                                  | complex    |
| x = \["elma", "muz", "çilek"]           | list       |
| x = ("elma", "muz", "çilek")            | tuple      |
| x = range(6)                            | range      |
| x = {"isim" : "Yunus", "yas" : 36}      | dict       |
| x = {"elma", "muz", "çilek"}            | set        |
| x = frozenset({"elma", "muz", "çilek"}) | frozenset  |
| x = True                                | bool       |
| x = b"Merhaba"                          | bytes      |
| x = bytearray(5)                        | bytearray  |
| x = memoryview(bytes(5))                | memoryview |

## 2. Veri Tipini Belirterek Değişken Oluşturma

Değişkenler dersinde anlattığımız üzere Python programlama dilinde bir değişken oluştururken o değişkenin tipini belirtecek bir terim kullanmanıza gerek yoktur. Python, oluşturduğunuz değişkene atayacağınız değer üzerinden otomatik olarak o değişkenin tipini algılayacaktır.

```python
a = 5      #Sayısal tip olan (int)
b = "5"    #Metin tipi olan (str)

print(type(a))    # <class 'int'>
print(type(b))    # <class 'str'>
```

Örnek kodda gördüğünüz gibi oluşturduğumuz `a` ve `b` değişkeninin sayı mı yoksa metin mi olduğunu Python otomatik olarak tespit etti ve tipini atadı. Fakat siz isterseniz oluşturacağınız değişkenin tipini kendiniz belirleyebilirsiniz. Bunun için aşağıdaki tabloyu inceleyebilirsiniz.

| Örnek                                   | Veri Tipi  |
| --------------------------------------- | ---------- |
| x = str("Merhaba Dünya")                | str        |
| x = int(20)                             | int        |
| x = float(20.5)                         | float      |
| x = complex(1j)                         | complex    |
| x = list(("elma", "muz", "çilek"))      | list       |
| x = tuple(("elma", "muz", "çilek"))     | tuple      |
| x = range(6)                            | range      |
| x = dict(isim="John", yas=36)           | dict       |
| x = set(("elma", "muz", "çilek"))       | set        |
| x = frozenset(("elma", "muz", "çilek")) | frozenset  |
| x = bool(5)                             | bool       |
| x = bytes(5)                            | bytes      |
| x = bytearray(5)                        | bytearray  |
| x = memoryview(bytes(5))                | memoryview |

{% hint style="info" %}
Elinizdeki bir değişkenin veri tipini öğrenebilmek için **type()** fonksiyonunu kullanabilirsiniz.
{% endhint %}

## 3. Veri Tipleri Arası Dönüşüm

Elinizde mevcut olan bir değişkenin tipini değiştirmek istediğinizde, örneğin **int** tipindeki bir sayıyı **float** tipine çevirmek için yukarıda yer alan örnekleri kullanabilirsiniz. Artı olarak şu örneği inceleyebilirsiniz;

```python
a = 5

print(a)          # 5
print(type(a))    # <class 'int'>

a = float(a)

print(a)          # 5.0
print(type(a))    # <class 'float'>
```

Aynı şekilde **int** tipindeki bir sayıyı string(metin) türündeki **str** tipine çevirmek aşağıdaki örneği inceleyebilirsiniz;

```python
a = 5

print(type(a))    # <class 'int'>

a = str(a)

print(type(a))    # <class 'str'>
```

Yukarıda veri tiplerine ait örnekleri gördük. Bundan sonraki derslerimizde her bir veri tipini tek tek detaylıca inceleyeceğiz.


# # Python Sayılar

Python sayılar (numbers) konusunu işliyoruz.

Python veri tiplerine genel bir baktıktan sonra ilk veri tip kategorimiz olan **Python Sayılar** ile derslerimize devam ediyoruz. Python programlama dilinde sayısal tiplerde üç adet veri tipimiz mevcut olup bunlar şunlardır; Bu üç değişken sayı tipi için küçük bir örnek verelim hemen:

```python
a = 5        # int
b = 46.53    # float
c = 3j       # complex
```

Değişkenlerimizin hangi veri tipinde olduğunu öğrenmek için **type()** fonksiyonunu kullandığımızı hatırlıyorsunuz. Öyleyse hemen yukarıdaki örnekte yer alan değişkenlerin tipini teyit edelim.

```python
print(type(a))    # <class 'int'>
print(type(b))    # <class 'float'>
print(type(c))    # <class 'complex'>
```

## 1. Int Veri Tipi

Python sayısal veri tiplerinden olan **int** (integer) veri tipi konumuzla başlayalım.

{% hint style="info" %}
Bir `int` değişken sonsuz uzunlukta pozitif ve negatif tam sayılardan oluşabilir. Sadece ondalık değerlere sahip olamaz.
{% endhint %}

```python
x = 10
y = 35656222554887711
z = -3255522

print(type(x))    # <class 'int'>
print(type(y))    # <class 'int'>
print(type(z))    # <class 'int'>
```

## 2. Float Veri Tipi

Python sayısal veri tiplerinden olan **float** (floating point number) veri tipi ile devam ediyoruz.

{% hint style="info" %}
Bir `float` değişken bir veya daha fazla uzunluktaki küsüratlı basamağa sahip pozitif ve negatif sayılardan oluşabilir.
{% endhint %}

```python
x = 1.10
y = 1.0
z = -35.59985

print(type(x))    # <class 'float'>
print(type(y))    # <class 'float'>
print(type(z))    # <class 'float'>
```

{% hint style="info" %}
Float veri tipinde `e` veya **E** ile 10 un katsayılarını belirtebilirsiniz.
{% endhint %}

```python
x = 15e3
y = 12E4
z = -87.7e100

print(x)    # 35000.0
print(y)    # 120000.0
print(z)    # -8.77e+101

print(type(x))    # <class 'float'>
print(type(y))    # <class 'float'>
print(type(z))    # <class 'float'>
```

## 3. Complex Veri Tipi

Python sayısal veri tiplerinden olan **complex** veri tipi ile devam ediyoruz.

{% hint style="info" %}
Bir **complex** veri tipinde sanal kısımlar **j** harfiyle belirtilir.
{% endhint %}

```python
x = 3+5j
y = 5j
z = -5j

print(x)    # (3+5j)
print(y)    # 5j
print(z)    # (-0-5j)

print(type(x))    # <class 'complex'>
print(type(y))    # <class 'complex'>
print(type(z))    # <class 'complex'>
```

## 4. Tip Dönüşümleri

Bir veri tipi `int()` , `float()` , ve `complex()` fonksiyonları kullanılarak başka bir veri tipine dönüşüm yapılabilir.

### 4.1 Int veri Tipinden float Veri Tipine Dönüşüm

Python programlamada **int** veri tipinden **float** veri tipine çevirme işlemi için **float()** fonksiyonunu kullanabilirsiniz.

```python
x = 3    # int

a = float(x)

print(a)            # 3.0

print(type(a))      # <class 'float'>
```

### 4.2 Float veri Tipinden int Veri Tipine Dönüşüm

Python programlamada **float** veri tipinden **int** veri tipine çevirme işlemi için **int()** fonksiyonunu kullanabilirsiniz.

```python
x = 7.3    # float

a = int(x)

print(a)            # 7

print(type(a))      # <class 'int'>
```

{% hint style="info" %}
Float veri tipinden int veri tipine dönüşüm yaparken elinizdeki float sayının en yakın olduğu taban veya tavan int sayıya dönüşmesi için **round()** fonksiyonunu kullanabilirsiniz.
{% endhint %}

```python
x = 7.3
y = 7.5
z = 7.8

a = round(x)
b = round(y)
c = round(z)

print(a)    # 7
print(b)    # 8
print(c)    # 8
```

### 4.3 Int veri Tipinden complex Veri Tipine Dönüşüm

Python programlamada **int** veri tipinden **complex** veri tipine çevirme işlemi için **complex()** fonksiyonunu kullanabilirsiniz.

```python
x = 3    # int

a = complex(x)

print(a)            # (3+0j)

print(type(a))      # <class 'complex'>
```

### 4.4 Float veri Tipinden complex Veri Tipine Dönüşüm

Python programlamada **float** veri tipinden **complex** veri tipine çevirme işlemi için **complex()** fonksiyonunu kullanabilirsiniz.

```python
x = 5.7    # float

a = complex(x)

print(a)            # (5.7+0j)

print(type(a))      # <class 'complex'>
```

{% hint style="warning" %}
Complex veri tipindeki bir sayıyı başka bir veri tipine çeviremezsiniz.
{% endhint %}

## 5. Rastgele Sayı Üretme & Oluşturma

Python özünde rastgele sayılar üretmek için bir **random()** fonksiyonu barındırmaz. Fakat ek modüller ile rastgele sayı oluşturma işlemi yapılabilir. Bunun için öncelikle `import random` komutu ile gerekli kütüphaneyi kodumuza eklememiz gerekiyor. Aşağıdaki örneği inceleyebilirsiniz.

```python
import random

print(random.randrange(1,10))
```

Bu örnek ile 1 ve 9 arasında rastgele sayılar üretebilirsiniz. Aşağıdaki örnek ile de bir tavan sayı belirleyip 0 ile o sayı arasında rastgele sayılar üretebilirsiniz.

```python
import random
print(random.randrange(3))
```

Bu örnekte oluşabilecek sayılar sadece 0,1 ve 2 dir.

## 6. Matematiksel İşlemler ve Fonksiyonlar

Bu bölümde Python'da sayılar üzerinde kullanabileceğimiz operantları ve en çok kullanılan fonksiyonları inceleyeceğiz.

```python
# Toplama İşlemi
>>> x + y

# Çıkarma İşlemi
>>> x - y

# Çarpma İşlemi
>>> x * y    

# Bölme İşlemi
>>> x / y

# Bölme İşlemi (Küsüratı siler)
>>> x // y

# Mod İşlemi
>>> x % y

# Sayıyı negatife çevirme
>>> -x

# Mutlak Değer
>>> abs(x)

# Kompleks Sayının Eşleniği
>>> c.conjugate()

# Bölme ve Mod İşlemi (x // y, x % y)
>>> divmod(x, y)

# X in Y üssü (ikiside aynı işlemi yapar)
>>> pow(x, y)
>>> x**y
```


# # Python Karakter Dizileri

Python karakter dizileri (strings) konusunu işliyoruz.

Her programlama dilinde olduğu gibi Python programlama dilinde de **karakter dizileri** yani **string** değişken tipi büyük önem arz eder. Çünkü tanımlayacağınız birçok değişken string ifadeler içerir. Üstelik string değişken tipleri üzerinden yürütebileceğiniz birçok Python fonksiyonu mevcuttur. Bir string yani `str` veri tipinde değerler **`"`** (çift tırnak), **`'`** (tek tırnak), `"""` (üç tırnak) ifadeleri arasında gösterilir.

```python
blog = "Kerteriz Blog" 
blog = 'Kerteriz Blog' 
blog = """Kerteriz Blog"""
```

Bu örnekte gördüğünüz her üç değişken de birebir aynıdır. Siz istediğiniz kullanımı tercih edebilirsiniz. Fakat bir kullanım belirledikten sonra değerinizin içinde aynı işareti kullanamazsınız çünkü Python değerin bitiş yerini orası belirler.

```python
#YANLIŞ
metin = 'Yunus'un arabası var'

#DOĞRU
metin = "Yunus'un arabası var"

#DOĞRU
metin = """Yunus'un arabası var"""
```

Bir string oluşturduğunuzda hangi işaret ile başlıyorsanız bitirirken de aynı işareti kullanmalısınız.

```python
#DOĞRU
isim = 'Kerteriz'

#DOĞRU
isim = "Kerteriz"

#YANLIŞ
isim = "Kerteriz'

#YANLIŞ
isim = "Kerteriz"""
```

{% hint style="info" %}
String (str) değişken tanımlarken birden fazla satırdan oluşan değerler oluşturabilirsiniz.
{% endhint %}

```python
a = '''Merhaba arkadaşlar,
Bu örnekte gördüğünüz gibi,
birden fazla satıra sahip
değişken oluşturabilirsiniz.'''

print(a)
```

## 1. String Değerler Aynı Zamanda Dizidir

Bir **string** veri tipinde değişken oluşturmuşsanız aynı zamanda bir dizi oluşturmuşsunuz demektir. Çünkü ders başlığında da yazdığımız gibi bir string değişken **karakter dizisi** şeklinde veri tipidir. Örneğin " **Kerteriz** " kelimesi `K` , `e` , `r` , `t` , `e` , `r` , `i` , `z` harflerinden meydana gelir. Bunu hemen başka bir örnekle gösterelim:

```python
sehir= "Ankara"

print(sehir[0])    #A
print(sehir[1])    #n
print(sehir[2])    #k
print(sehir[3])    #a
print(sehir[4])    #r
print(sehir[5])    #a
```

{% hint style="info" %}
Dizilerde (ilerleyen derslerde göreceğiz) index her zaman 0 dan başlar. Yani 0.index ilk elemandır.
{% endhint %}

## 2. Metin Dilimleme (String Parçalama)

Programlamanızı yaparken elinizdeki string değişkenlerin belirli bir parçasını kullanmak, başından veya sonundan kırpmak, tersine çevirmek gibi işlemlere tabi tutmak isteyebilirsiniz. İlk olarak elinizdeki metinin bir karakter dizisi olduğunu hatırlayalım.

```python
isim = "Kerteriz"

isim[0] --> K
isim[1] --> e
isim[2] --> r
isim[3] --> t
isim[4] --> e
isim[5] --> r
isim[6] --> i
isim[7] --> z

#Tersinede işlem yapabiliriz
isim[-1] --> z
isim[-2] --> i
isim[-3] --> r
isim[-4] --> e
isim[-5] --> t
isim[-6] --> r
isim[-7] --> e
isim[-8] --> K
```

Öyleyse elimizdeki metin üzerinde x. karakterden y. karaktere kadar kırpma işlemini gerçekleştirelim.

```python
isim = "kerteriz ile Python öğreniyorum"

# 4. indeksten 10.indekse kadar
isim[4:10] --> eriz i

# En baştan 10.indekse kadar
isim[:10] --> kerteriz i

# 4. indeksten sonuna kadar
isim[4:] --> eriz ile Python öğreniyorum'

# İki değer de belirtilmemişse tüm stringi al.
isim[:] --> kerteriz ile Python öğreniyorum

#Son karaktere kadar al.
isim[:-1] --> kerteriz ile Python öğreniyoru'

# Baştan sona 2 değer atlaya atlaya stringi al.
isim[::2] --> krei l yhnörnyrm'

# 4.indeksten 12'nci indekse 3'er atlayarak stringi al.
isim[4:12:3] --> ezl
```

Bir string değişken ile metini tersine çevirmek, metini tersinden yazmak için aşağıdaki örneği inceleyebilirsiniz.

```python
isim = "kerteriz ile Python öğreniyorum"

# Baştan sona -1 atlayarak stringi al.
isim[::-1] --> muroyinerğö nohtyP eli ziretrek
```

## 3. String Fonksiyonları

### 3.1 Metinin Karakter Uzunluğunu Öğrenme

Elinizdeki string değişkenin kaç karakterden oluştuğunu öğrenmek için **len()** fonksiyonunu kullanabilirsiniz.

```python
a = "Merhaba Dünya!"

print(len(a)) # 14
```

### 3.2 Metindeki Boşlukları Temizleme

Bir metinin başındaki ve sonundaki boşlukları temizlemek için **strip()** fonksiyonunu kullanabilirsiniz.

```python
a = " Suyu israf etmeyin! "

print(a.strip()) # "Suyu israf etmeyin!"
```

### 3.3 Metindeki Tüm Karakterleri Büyük Harfe Çevirme

Elinizdeki metini tamamen büyük harflere çevirmek istiyorsanız **upper()** fonksiyonunu kullanabilirsiniz.

```python
a = "Ağaçlar ciğerlerimizdir"

print(a.upper()) # AĞAÇLAR CIĞERLERIMIZDIR
```

### 3.4 Metindeki Tüm Karakterleri Küçük Harfe Çevirme

Elinizdeki metini tamamen küçük harflere çevirmek istiyorsanız **lower()** fonksiyonunu kullanabilirsiniz.

```python
a = "AĞAÇLAR CİĞERLERİMİZDİR"
print(a.lower()) # ağaçlar ciğerlerimizdir
```

### 3.5 Metindeki Karakterleri Başka Karakterlerle Değiştirmek

Metindeki bir karakter veya bir kelime grubunu başka bir karakter veya metin grubuyla değiştirmek istediğinizde **replace()** fonksiyonunu kullanabilirsiniz.

```python
a = "Muz tatlı bir meyvedir"

print(a.replace("Muz", "Çilek")) #Çilek tatlı bir meyvedir
```

### 3.6 Metini İstenilen Bir Karakterden Bölmek

Elinizdeki belirlediğiniz bir karakterden bölerek diziye atayabilirsiniz. Aşağıdaki örnekte örnek kullanımını görebilirsiniz.

```python
a = "Kayseri,Nevşehir,Kırşehir İç Anadolu bölgesindedir"

print(a.split(",")) # ['Kayseri', 'Nevşehir', 'Kırşehir İç Anadolu bölgesindedir']
```

## 4. Metin İçinde Karakter veya Metin Aramak

Bir metin editöründe nasıl karakter veya metin arayabiliyorsanız Python programlama diliyle de string değişkeniniz içinde **`in`** ve **`not in`** terimleriyle herhangi bir karakter veya metin arayabilirsiniz.

```python
txt = "En sevdiğim hava yağmurlu havadır"

x = "mur" in txt

print(x)            # True
```

Dönecek sonucu ter çevirmek istiyorsanız **not** terimini kullanabilirsiniz.

```python
txt = "En sevdiğim hava yağmurlu havadır"

x = "mur" not in txt 

print(x) # False
```

{% hint style="info" %}
`True` ve `False` mantıksal (bool) ifadelerdir. Doğruysa True, Yanlışsa False değeri döner.
{% endhint %}

## 5. Metin Birleştirme, Toplama ve Çarpma

Bazı durumlarda elinizde bulunan string değerleri birbirleriyle birleştirmek ve yan yana eklemek isteyebilirsiniz. Bunun için matematiksel ifade olan **+** işareti kullanılır. Örneklerini aşağıda görebilirsiniz.

```python
a = "Kerteriz"
b = " "
c = "Blog"

print(a+b+c)                     # Kerteriz Blog
print(c + "yazmak düzeldir")     # Blog yazmak güzeldir
```

Bir kelimeyi veya karakteri istediğimiz adette yazmak için matematiksel ifade olan **\*** işareti kullanılır. Örneklerini aşağıda görebilirsiniz.

```python
a = "elma"

print(a*3)        # elmaelmaelma
```

## 6. String Format Kullanımı

Yukarıdaki örneklerde birden fazla değişkeni birleştirmek için **+** işaretini nasıl kullanabileceğimizi gördük. Peki bir metin içinde belirli alanlar belirleyerek bu alanlara denk gelecek değerleri nasıl yazdırabiliriz? Bunun için **format** özelliğini kullanarak **{}** işaretinin geldiği yerlere sırasıyla değerlerimizi oturtabiliriz.

```python
yas = 24
hava = "Yağmurlu"
hedef = "Okula"

metin = "Dün akşam {} yaşlarında bir genç {} havada yürüyerek {} gidiyordu"

print(metin.format(yas,hava,hedef))       # Dün akşam 24 yaşlarında bir genç Yağmurlu havada yürüyerek Okula gidiyordu
```

## 7. Kaçış (Escape) Karakterleri

Dersimizin en başında dediğimiz gibi bir string değişken belirlerken hangi işaretle başladıysanız o işaretle bitirmelisiniz ve aynı işaretten değişken içinde kullanmamalısınız. Bunu öncelikle bir hatırlayalım.

```python
metin = "Bu aralar "Şeker Portakalı" kitabını okuyorum"

print(metin) # !! HATA !!
```

Böyle bir kullanımda hata alacaksınızdır. Çünkü ilk `"` işaretinden sonra gelen `"` işareti değişken tanımlamayı bitirir ama siz yazmaya devam ettiğiniz için hata alırsınız. Bu hatanın 2 çözüm yöntemi vardır. İlki `"` işareti yerine `'` işareti kullanabilirsiniz.

```python
metin = "Bu aralar 'Şeker Portakalı' kitabını okuyorum"

print(metin) # Bu aralar 'Şeker Portakalı' kitabını okuyorum
```

Fakat siz `"` işaretini kullanmak istiyorsanız devreye **kaçış karakterleri** dediğimiz **\\** işaretinin özel kullanımı giriyor. Eğer **"** işaretinin başlarına **\\** işaretini koyarsak Python bu işaretten sonra gelen karakteri normal bir karakter gibi yorumlayacak ve metine dahil edecektir.

```python
metin = "Bu aralar \"Şeker Portakalı\" kitabını okuyorum"

print(metin) # Bu aralar "Şeker Portakalı" kitabını okuyorum
```

Örnekte gördüğünüz gibi herhangi bir özel karakter kullanmak istediğinizde **\\** işareti sizi kurtaracaktır. Aşağıdaki tablodan diğer örnekleri görebilirsiniz.


# # Python Boolen

Python boolen konusunu işliyoruz.

Matematikte mantık dediğimizde aklımıza nasıl **doğru** ve **yanlış** terimleri geliyorsa Python programlama dilinde de **boolen** veri tipinde **True** ve **False** değerleri karşımıza çıkıyor. Herhangi iki değeri karşılaştırdığınızda veya bir ifadenin doğrulunu kontrol ederken **bool** veri tipini kullanabilirsiniz.

```python
print(5 > 4)        # True
print(5 == 4)       # False
print(5 < 4)        # False
```

Örnekteki gibi Python ile bir durumu kontrol ettiğinizde size True veya False olarak cevap döner. Aynı şekilde **if** kontrol durumları ile de bool ifadeleri kullanabilirsiniz.

```python
a = 10
b = 20

if a > b:
    print("a büyüktür b den")
else:
    print("b büyüktür a dan")
```

Python programlama dilinde nasıl ki int, str gibi veri tiplerinde değişkenler oluşturabiliyorsanız aynı şekilde **bool** veri tipinde de değişkenler oluşturabilirsiniz ve mevcut değişkenleri kontrol edebilirsiniz.

```python
a = bool(True)
b = bool(False)

print(a)        # True
print(b)        # False
```

{% hint style="info" %}
Mevcut değişkenleri kontrol ederken eğer değişken **0** harici herhangi bir değere sahipse `True` , 0 ve boş değerlere sahipse **False** değeri döner.
{% endhint %}

```python
x = "Merhaba"
y = 15
z = ["elma", "çilek", "muz"]

print(bool(x))    # True
print(bool(y))    # True
print(bool(z))    # True
```

Bu örnekte değişkenler bir değere sahip olduğu için True döndü.

```python
bool(False)    # False
bool(None)     # False
bool(0)        # False
bool("")       # False
bool(())       # False
bool([])       # False
bool({})       # False
```

Burada ise 0 ve boş değerler olduğu için sonuçlarımız False döndü. Bool değerler en çok fonksiyonlarda kullanılır ve hayati bir öneme sahiptir. Bir fonksiyonun dönüş değerini boolen ayarlayarak kontrollerinizi gerçekleştirebilirsiniz. Aşağıdaki örneği inceleyelim:

```python
def ciftsayikontrol(x):
    if x % 2 == 0:
        return True
    else:
        return False

print(ciftsayikontrol(5))        # False
print(ciftsayikontrol(8))        # True
```

Örnekte fonksiyona gönderdiğimiz sayının çift veya tek sayı olma durumunu kontrol ediyoruz. Siz de yazdığınız fonksiyonlara bool dönüş değerleri vererek kodlamanıza kontroller ekleyebilir ve bu doğrultuda kodlamanın seyrini değiştirebilirsiniz.


# # Python Operatörler

Python operatörler (operators) konusunu işliyoruz.

Diğer tüm programlama dillerinde olduğu gibi Python programlama dilinde de operatörler değişkenler ve değerler üzerinde işlem gerçekleştirmek için kullanılırlar. Buradaki işlem birçok kategoriye sahiptir. Şimdi bu kategorileri yazalım ve ardından tek tek inceleyelim;&#x20;

* Aritmetik (arithmetic) operatörler
* Atama (assignment) operatörleri
* Karşılaştırma (comparison) operatörleri
* Mantıksal (logical) operatörler
* Kimlik (identity) operatörleri
* Üyelik (membership) operatörleri
* Bit (bitwise) operatörleri

## 1. Aritmetik Operatörler

Python aritmetik (arithmetic) operatörler sayılar üzerinde matematiksel işlemler yapılırken kullanılırlar. `a=5` ve `b=2` değişkenleri üzerinden aşağıdaki örnek kullanımları inceleyebilirsiniz.

| Operatör | Açıklama  | Örnek         |
| -------- | --------- | ------------- |
| +        | Toplama   | a + b # 7     |
| -        | Çıkarma   | a - b # 3     |
| \*       | Çarpma    | a \* b # 10   |
| /        | Bölme     | a / b # 2.5   |
| %        | Mod Alma  | a % b # 1     |
| \*\*     | Üs Alma   | a \*\* b # 25 |
| //       | Tam Bölüm | a // b # 2    |

## 2. Atama Operatörleri

Python Atama operatörleri değerleri değişkenlere atarken kullanırlar. Tabi bu atamaları yaparken aynı zamanda aritmetik operatörleri de kullanarak pratik kod yazabilirsiniz. `a=5` ve `b=2` değişkenleri üzerinden aşağıdaki örnek kullanımları inceleyebilirsiniz.

| Operatör | Açıklama           | Eş Kullanım  |
| -------- | ------------------ | ------------ |
| =        | Eşittir            | a = b        |
| +=       | Toplayarak Eşitle  | a = a + b    |
| -=       | Çıkararak Eşitle   | a = a - b    |
| \*=      | Çarparak Eşitle    | a = a \* b   |
| /=       | Bölerek Eşitle     | a = a / b    |
| %=       | Mod Alarak Eşitle  | a = a % b    |
| \*\*=    | Üs Alarak Eşitle   | a = a \*\* b |
| //=      | Tam Bölerek Eşitle | a = a // b   |
| &=       | Bit AND İşlemi     | a = a & b    |
| \|=      | Bit OR İşlemi      | a = a \| b   |
| ^=       | Bit XOR İşlemi     | a = a + b    |

## 3. Karşılaştırma Operatörleri

Python karşılaştırma (comparison) operatörler ile sayılar üzerinde büyük, küçük ve eşit ifadeleriyle karşılaştırma yapabilirsiniz. `a=5` ve `b=2` değişkenleri üzerinden aşağıdaki örnek kullanımları inceleyebilirsiniz.

| Operatör | Açıklama      | Eş Kullanım          |
| -------- | ------------- | -------------------- |
| ==       | Eşit mi       | a == b      # False  |
| !=       | Eşit değil mi | a != b       # True  |
| >        | Büyük mü      | a > b        # True  |
| <        | Küçük mü      | a < b        # False |
| >=       | Büyük eşit mi | a >= b      # True   |
| <=       | Küçük eşit mi | a <= b      # False  |

## 4. Mantıksal Operatörleri

Python mantıksal (logical) operatörler ile şartlı durumları birleştirebilirsiniz. `a=5` ve `b=2` değişkenleri üzerinden aşağıdaki örnek kullanımları inceleyebilirsiniz.

| Operatör | Açıklama                    | Eş Kullanım                         |
| -------- | --------------------------- | ----------------------------------- |
| and      | Her iki durumda doğruysa    | a < 5 and b < 10             # True |
| or       | Herhangi bir durum doğruysa | x < 5 and x == 10           # True  |
| not      | Durumu ters çevir           | not(a < 5 and b < 10)    # False    |

## 5. Kimlik Operatörleri

Python kimlik (identity) operatörler ile değişkenleri karşılaştırarak aynı olup olmadıklarını kontrol edebilirsiniz. `a=5` ve `b=2` değişkenleri üzerinden aşağıdaki örnek kullanımları inceleyebilirsiniz.

| Operatör | Açıklama               | Eş Kullanım       |
| -------- | ---------------------- | ----------------- |
| is       | Aynı objelerse doğru   | a is b # False    |
| is not   | Farklı objelerse doğru | a is not b # True |

## 6. Üyelik Operatörleri

Python üyelik (membership) operatörler ile bir değişkenin bir dizi, liste,küme vs içinde olup olmadığını kontrol edebilirsiniz. `a=["elma", "armut", "çilek"]` değişkenleri üzerinden aşağıdaki örnek kullanımları inceleyebilirsiniz.

| Operatör | Açıklama           | Eş Kullanım                   |
| -------- | ------------------ | ----------------------------- |
| in       | İçinde varsa doğru | "armut" in a        # True    |
| not in   | İçinde yoksa doğru | "karpuz" not in a      # True |

## 7. Bit Operatörleri

Python bit (bitwise) operatörler ile değişkenleri karşılaştırarak `AND` , `OR` , `XOR` , `NOT` , `Sağa Kaydırma` ve `Sola Kaydırma` işlemlerini gerçekleştirebilirsiniz. Örnek kullanımları aşağıdan inceleyebilirsiniz.

| Operatör | Açıklama            |
| -------- | ------------------- |
| &        | AND işlemi          |
| \|       | OR işlemi           |
| ^        | XOR işlemi          |
| \~       | \~x = -(x+1) işlemi |
| <<       | Sola kaydırma       |
| >>       | Sağa kaydırma       |

**&** operatörü ile elinizdeki bir sayıyı başka bir sayı ile bit düzeyinde **AND** işlemine tabi tutabilirsiniz. Örnek kullanım aşağıdadır:

```python
a = 3
# bit değeri: 0011

b = 5
# bit değeri: 0101

a &= b

#         0011
#(AND)    0101
#-------------
#         0001


print(a)    # 1
```

**`|`** operatörü ile elinizdeki bir sayıyı başka bir sayı ile bit düzeyinde **OR** işlemine tabi tutabilirsiniz. Örnek kullanım aşağıdadır:

```python
a = 3
# bit değeri: 0011

b = 5
# bit değeri: 0101

a |= b

#         0011
#(OR)     0101
#-------------
#         0111


print(a)    # 7
```

**`^`** operatörü ile elinizdeki bir sayıyı başka bir sayı ile bit düzeyinde **XOR** işlemine tabi tutabilirsiniz. Örnek kullanım aşağıdadır:

```python
a = 3
# bit değeri: 0011

b = 5
# bit değeri: 0101

a ^= b

#          0011
#(XOR)     0101
#--------------
#          0110


print(a)    # 6
```

`~` operatörü ile elinizdeki bir sayıyı **\~x = -(x+1)** işlemine tabi tutabilirsiniz. Örnek kullanım aşağıdadır:

```python
a = 3
# bit değeri: 0011

a = ~a

#-(x+1)    0011
#--------------
#         -0100


print(a)    # -4
```

**`>>`** operatörü ile elinizdeki bir sayının bit değeri üzerinden sağa kaydırma işlemi yapabilirsiniz. Soldan gelen yeni bitle ise 0 değerini alır. Örnek kullanım aşağıdadır:

```python
a = 5
# bit değeri: 0101

a >>= 2
# yeni bit değeri: 0001

print(a)    #1
```

**`<<`** operatörü ile elinizdeki bir sayının bit değeri üzerinden sola kaydırma işlemi yapabilirsiniz. Sağdan gelen yeni bitle ise 0 değerini alır. Örnek kullanım aşağıdadır:

```python
a = 13
# bit değeri: 1101

a <<= 5
# yeni bit değeri: 110100000

print(a)    #416
```


# # Python Diziler

Python diziler (arrays) konusunu işliyoruz.

Python diziler (array) veya diğer bilinen adıyla koleksiyonlar (collections) değişken tiplerinde dört farklı veri tipi vardır. Bunlar;

1. **Liste (List);** sıralanabilen ve değiştirilebilen elemanlardan oluşur. Aynı değerden birden fazla barındırabilir.
2. **Demet (Tuple);** sıralanabilen ama değiştirilemeyen elemanlardan oluşur. Aynı değerden birden fazla barındırabilir.
3. **Küme (Set);** sıralanamayan ve indekslenemeyen elemanlardan oluşur. Aynı değerden birden fazla eleman barındırmaz.
4. **Sözlük (Dictionary);** değiştirilebilen, indekslenebilen ama sıralanamayan elemanlardan oluşur. Aynı değerden birden fazla eleman barındırmaz.

&#x20;Özetle;

| Veri Tipi | Sıralanabilir (Ordered) | Değiştirilebilir (Changeable) | İndexlenebilir (Indexed) | Kopya Eleman (Duplicated) |
| --------- | ----------------------- | ----------------------------- | ------------------------ | ------------------------- |
| Liste     | +                       | +                             | +                        | +                         |
| Demet     | +                       | -                             | +                        | +                         |
| Küme      | -                       | -                             | -                        | -                         |
| Sözlük    | -                       | +                             | +                        | -                         |

{% hint style="info" %}
Python programlama dilinde diziler yani koleksiyonlar çok önemli bir veri tipidir. Bu nedenle iyi öğrenilmeleri ve doğru veri tipinin seçilmesi programlarınızda gözle görülür etkiler yaratacaktır.
{% endhint %}

Bu dört veri tipini sırasıyla anlatmaya başlıyoruz..


# # Python Listeler

Python listeler (lists) konusunu işliyoruz.

Python koleksiyonlar (diziler) altında yer alan **liste (list)** veri tipimiz *sıralanabilen* , *değiştirilebilen* , *indekslenebilen* ve *çoğul elemana izin veren* bir veri tipidir. Köşeli parantezlerle `[ ]` oluşturulur.

```python
liste = []
```

Köşeli parantezlere oluşturulan listeler, en başta elemanlarla birlikte de oluşturulabilirler.

```python
liste = ["Ankara","İstanbul","Kayseri"]
```

Aynı zamanda bir liste **list()** fonksiyonu ile de oluşturulabilir ve constructor yöntemiyle başlangıçta elemanları ayarlanabilir.

```python
liste = list()

liste = list(("Ankara","İstanbul","Kayseri"))
```

Oluşturduğumuz `liste` değişkenlerinin tipini kontrol edelim.

```python
print(type(liste)) # <class 'list'>
```

## 1. Liste Elemanlarına Erişim

Python programlama dilinde elinizdeki bir listenin elemanlarına ulaşabilmek için indeksleri kullanmalısınız. Aşağıdaki örnekle indeksleri nasıl kullanacağınızı gösterelim.

```python
liste = ["Sal","Vapur","Feribot","Korvet","Fırkateyn"]

print(liste[0])    # Sal
print(liste[1])    # Vapur
print(liste[2])    # Feribot
print(liste[3])    # Korvet
print(liste[4])    # Fırkateyn
```

{% hint style="warning" %}
İndeks her zaman **0** dan başlar. Yani bir listede ilk elemanın indeksi 0 dır.
{% endhint %}

## 2. Negatif İndeksleme

Negatif indeks kullanarak bir listeyi tersten başlayarak ele alabilirsiniz. Örnek üzerinde görelim hemen.

```python
liste = ["Sal","Vapur","Feribot","Korvet","Fırkateyn"]

print(liste[-1])    # Fırkateyn
print(liste[-2])    # Korvet
print(liste[-3])    # Feribot
print(liste[-4])    # Vapur
print(liste[-5])    # Sal
```

{% hint style="warning" %}
Negatif indeks normal indeksin aksine **-1** den başlar. Yani bir listede son elemanın indeksi -1 dir.
{% endhint %}

## 3. Bir Listeden Yeni Liste Oluşturma (İndeks)

Elimizde mevcut olan bir listeden indeks belirterek yeni bir liste oluşturabiliriz. Örneğin mevcut listenin 2.indeksinden 5.indeksine kadar ( *5 dahil değil* ) olan elemanlarla yeni bir liste oluşturalım.

```python
liste = ["a","b","c","d","e","f","g"]

yeniliste = liste[2:5]

print(yeniliste)    #["c","d","e"]
```

{% hint style="info" %}
Bu şekilde yeni liste oluştururken `[x:y]` ifadesinde x dahil, y dahil değildir. Ayrıca indeksin **0** dan başladığını unutmayınız!
{% endhint %}

## 4. Bir Listeden Yeni Liste Oluşturma (Negatif İndeks)

Elimizdeki listeden yeni bir liste oluştururken negatif indeksleri de kullanabiliriz.

```python
liste = ["a","b","c","d","e","f","g"]

yeniliste = liste[-3:-1]

print(yeniliste)    #["e","f"]
```

{% hint style="info" %}
Bu şekilde yeni liste oluştururken `[-x:-y]` ifadesinde -x dahil, -y dahil değildir. Ayrıca negatif indeksin **-1** den başladığını unutmayınız!
{% endhint %}

## 5. Liste Elemanlarını Sıralayarak Ekrana Yazdırma

Yeri geldiğinde liste elemanlarınızı ekrana sırasıyla yazdırmak, elemanlar üzerinde sırasıyla işlem yapmak isteyebilirsiniz. Bunun için **for** döngümüzü kullanacağız.

```python
liste = ["a","b","c","d"]

for x in liste:
    print(x)
```

Bu şekilde listenin tüm elemanları x değeri üzerinden otomatik olarak listelenecek ve dizi elemanı bittiğinde döngü duracaktır.

## 6. Liste Eleman Sayısını Öğrenme

Elinizde olan bir listenin eleman sayısını öğrenmek için **len()** fonksiyonunu kullanacağız.

```python
liste = ["a","b","c","d"]

print(len(liste))    #4
```

Eğer özellikle bir elemanın listede kaç adet bulunduğunu öğrenmek isterseniz de **count()** fonksiyonunu kullanmanız gerekiyor.

```python
liste = ["a","b","c","c","d","c"]

sayac = liste.count("c")

print(sayac)    #3
```

## 7. Liste Elemanının Değerini Değiştirme

Listeler ile çalışırken listede mevcut olan bir elemanın değerini rahatlıkla değiştirebilirsiniz. Bunun için elemanın indeks değerini bilmeniz yeterlidir.

```python
meyveler = ["kivi","çilek","muz","pırasa"]

meyveler[3] = "armut"

print(meyveler)    # ["kivi","çilek","muz","armut"]
```

## 8. Listeye Yeni Eleman Ekleme

Listeler ile çalışırken listenin sonuna rahatlıkla yeni bir eleman ekleyebilirsiniz. Bunun için **append()** fonksiyonunu kullanacağız.

```python
meyveler = ["kivi","çilek"]

meyveler.append("muz")

print(meyveler)    # ["kivi","çilek","muz"]
```

Eğer listenin sonuna değilde belirlediğiniz indeks numarasına eleman eklemek istiyorsanız **insert()** fonksiyonunu kullanmalısınız.

```python
meyveler = ["kivi","çilek"]

meyveler.insert(1,"muz")

print(meyveler)    # ["kivi","muz","çilek"]
```

## 9. Listeden Bir Eleman Çıkarma

Listenizden bir eleman çıkarmak istiyorsanız bunun dört yöntemi vardır. İlki listenin en sonundaki elemanı listeden atmaktır ve bunun için **pop()** fonksiyonunu kullanmalısınız.

```python
meyveler = ["kivi","çilek","muz","armut"]

meyveler.pop()

print(meyveler)    # ["kivi","çilek","muz"]
```

İkinci yöntem çıkarmak istediğiniz elemanı belirterek **remove()** fonksiyonunu kullanmaktır.

```python
meyveler = ["kivi","çilek","muz","armut"]

meyveler.remove("çilek")

print(meyveler) # ["kivi","muz","armut"]
```

Üçüncü yöntem çıkarmak istediğiniz elemanın indeksini belirterek **del** terimini kullanmaktır.

```python
meyveler = ["kivi","çilek","muz","armut"]

del meyveler[0]

print(meyveler) # ["çilek","muz","armut"]
```

Son ve en sert yöntemde tüm listeyi temizlemektir. Listedeki tüm elemanları çıkarıp boş bir liste elde etmek için **clear()** fonksiyonunu kullanabilirsiniz.

```python
meyveler = ["kivi","çilek","muz","armut"]

meyveler.clear()

print(meyveler) # []
```

## 10. Liste Kopyalamak ve Çoğaltmak

Elimizde olan bir listeyi kopyalayarak çoğaltmak istiyorsak **copy()** fonksiyonunu kullanabiliriz.

```python
liste = ["a","b","c","d"]

yeniliste = liste.copy()

print(yeniliste) # ["a","b","c","d"]
```

Liste kopyalama için kullanılan diğer bir yöntem de yeni bir liste oluşturulurken kopyalanacak listeyi belirtmektir.

```python
liste = ["a","b","c","d"]

yeniliste = list(liste)

print(yeniliste) # ["a","b","c","d"]
```

## 11. İki Farklı Listeyi Birleştirmek

Birbirinden farklı veya aynı iki listeyi birleştirmek için **+** operatörünü kullanabiliriz.

```python
liste1 = ["A","B","C"] liste2 = ["D","E"]

liste3 = liste1 + liste2

print(liste3) # ["A","B","C","D","E"]
```

Şimdi ise sırf bu liste birleştirme işlemi için oluşturulmuş **extend()** fonksiyonunu kullanalım.

```python
liste1 = ["A","B","C"] liste2 = ["D","E"]

liste1.extend(liste2)

print(liste1) # ["A","B","C","D","E"]
```

Kolay yöntemleri öğrendikten sonra şimdi de biraz daha uzun yöntemini görelim.

```python
liste1 = ["A","B","C"] liste2 = ["D","E"]

for x in liste2: liste1.append(x)

print(liste1) # ["A","B","C","D","E"]
```

## 12. Liste Elemanlarını Sıralamak

Liste elemanlarınızı küçükten büyüğe veya büyükten küçüğe sıralamak istediğiniz zaman **sort()** fonksiyonunu kullanabilirsiniz.

```python
liste = [14,36,2,95,43,0,66]

liste.sort()

print(liste) # [0, 2, 14, 36, 43, 66, 95]
```

Tam tersi yani büyükten küçüğe sıralamak için **reverse=True** terimini kullanmalısınız.

```python
liste = [14,36,2,95,43,0,66]

liste.sort(reverse=True)

print(liste) # [95, 66, 43, 36, 14, 2, 0]
```

## 13. Bir Elemanın İndeksini Bulmak

Elimizdeki listeden bir elemanının listedeki indeksini bulmak için **index()** fonksiyonunu kullanabilirsiniz.

```python
liste = [14,36,2,95,43,0,66]

print(liste.index(95)) # 3
```

## 14. Bir Elemanın Varlığını Kontrol Etme

Listede bir elemanın var olup olmadığını kontrol etmek için **in** terimini kullanabiliriz.

```python
liste = ["A","B","C","D","E"]

if "C" in liste: 
    print("Evet var!") 
else: 
    print("Hayır yok!")
    
# Evet var!
```


# # Python Demetler

Python demetler (tuples) konusunu işliyoruz.

Python koleksiyonlar (diziler) altında yer alan **demet (tuple)** veri tipimiz *sıralanabilen* , *indekslenebilen, çoğul elemana izin veren* ama değiştirilemeyen bir veri tipidir. Yuvarlak parantezlerle `( )` oluşturulur.

```python
demet = ()
```

Parantezlere oluşturulan demetler, en başta elemanlarla birlikte de oluşturulabilirler.

```python
demet = ("elma","armut","çilek")
```

Aynı zamanda bir liste **tuple()** fonksiyonu ile de oluşturulabilir ve constructor yöntemiyle başlangıçta elemanları ayarlanabilir.

```python
demet = tuple()

demet = tuple(("Ankara","İstanbul","Kayseri"))
```

{% hint style="warning" %}
Eğer tek elemanlı bir demet oluşturmak istiyorsanız ilk elemandan sonra **, (virgül)** işareti koymalısınız. Aksi takdirde veri tipiniz str olur.
{% endhint %}

{% tabs %}
{% tab title="Tuple" %}

```python
demet = ('a',)

print(type(demet))    # <class 'tuple'>
```

{% endtab %}

{% tab title="String" %}

```python
demet = ('a')

print(type(demet))    # <class 'str'>
```

{% endtab %}
{% endtabs %}

Oluşturduğumuz `demet` değişkenlerinin tipini kontrol edelim.

```python
print(type(demet))    # <class 'tuple'>
```

## 1. Demet Elemanlarına Erişim

Python programlama dilinde elinizdeki bir demetin elemanlarına ulaşabilmek için indeksleri kullanmalısınız. Aşağıdaki örnekle indeksleri nasıl kullanacağınızı gösterelim.

```python
demet = ("Ceviz","Fındık","Fıstık","Leblebi")

print(demet[0]) # Ceviz 
print(demet[1]) # Fındık 
print(demet[2]) # Fıstık 
print(demet[3]) # Leblebi
```

{% hint style="warning" %}
İndeks her zaman **0** dan başlar. Yani bir demette ilk elemanın indeksi 0 dır.
{% endhint %}

## 2. Negatif İndeksleme

Negatif indeks kullanarak bir demeti tersten başlayarak ele alabilirsiniz. Örnek üzerinde görelim hemen.

```python
demet = ("Ceviz","Fındık","Fıstık","Leblebi")

print(demet[-1]) # Leblebi 
print(demet[-2]) # Fıstık 
print(demet[-3]) # Fındık 
print(demet[-4]) # Ceviz
```

## 3. Bir Demetten Yeni Demet Oluşturma (İndeks)

Elimizde mevcut olan bir demetten indeks belirterek yeni bir demet oluşturabiliriz. Örneğin mevcut demetin 2.indeksinden 5.indeksine kadar ( *5 dahil değil* ) olan elemanlarla yeni bir demet oluşturalım.

```python
demet = ("a","b","c","d","e","f","g")

yenidemet = demet[2:5]

print(yenidemet) #("c","d","e")
```

{% hint style="info" %}
Bu şekilde yeni demet oluştururken `[x:y]` ifadesinde x dahil, y dahil değildir. Ayrıca indeksin **0** dan başladığını unutmayınız!
{% endhint %}

## 4. Bir Demetten Yeni Demet Oluşturma (Negatif İndeks)

Elimizdeki demetten yeni bir demet oluştururken negatif indeksleri de kullanabiliriz.

```python
demet = ("a","b","c","d","e","f","g")

yenidemet = demet[-3:-1]

print(yenidemet) #("e","f")
```

{% hint style="info" %}
Bu şekilde yeni demet oluştururken `[-x:-y]` ifadesinde -x dahil, -y dahil değildir. Ayrıca negatif indeksin **-1** den başladığını unutmayınız!
{% endhint %}

## 5. Demet Elemanlarını Sıralayarak Ekrana Yazdırma

Yeri geldiğinde demet elemanlarınızı ekrana sırasıyla yazdırmak, elemanlar üzerinde sırasıyla işlem yapmak isteyebilirsiniz. Bunun için **for** döngümüzü kullanacağız.

```python
demet = ("a","b","c","d")

for x in demet: print(x)
```

Bu şekilde demetin tüm elemanları x değeri üzerinden otomatik olarak listelenecek ve dizi elemanı bittiğinde döngü duracaktır.

## 6. Demet Eleman Sayısını Öğrenme

Elinizde olan bir demetin eleman sayısını öğrenmek için **len()** fonksiyonunu kullanacağız.

```python
demet = ("a","b","c","d")

print(len(demet)) #4
```

Eğer özellikle bir elemanın destede kaç adet bulunduğunu öğrenmek isterseniz de **count()** fonksiyonunu kullanmanız gerekiyor.

```python
demet = ("a","b","c","c","d","c")

sayac = demet.count("c")

print(sayac) #3
```

## 7. Demet Elemanının Değerini Değiştirme

Bu başlığı görünce şaşırmış olabilirsiniz çünkü konunun en başında demet elemanlarının **değiştirilemeyeceğini** söylemiştik. Bir demet oluşturduğunuzda elemanlarına artık indekslerle ulaşarak **değiştiremezsiniz** .

```python
meyveler = ("kivi","çilek","muz","karpuz")

meyveler[3] = "armut" # !!! HATA VAR !!!
```

Gördüğünüz gibi demetin bir elemanını değiştirmeye çalıştığınızda hata alacaksınızdır. Fakat elinizdeki demetin bir elemanını gerçekten değiştirmeye ihtiyaç duyduğunuzda aşağıdaki gibi dolaylı bir yöntem izleyebilirsiniz.

```python
x = ("kivi","çilek","muz","karpuz") 
y = list(x)

y[1] = "avakado" 
x = tuple(y)

print(x) # ("kivi","çilek","muz","karpuz")
```

Örnekteki gibi elimizde olan bir demeti önce listeye çevirerek elemanlarını indekslerle değiştirebilir hale getirdik. Ardından değiştirme işlemini yaptıktan sonra listemizi tekrar demete çeviriyoruz ve dolaylı yoldan demetimizi düzenlemiş oluyoruz.

## 8. Demete Yeni Eleman Ekleme

Bir demete yeni bir eleman **ekleyemezsiniz.** Bunun yerine yukarıdaki örnekte olduğu gibi önce listeye çevirip ekleme işlemini yaptıktan sonra tekrar demete çevirebilirsiniz.

## 9. Listeden Bir Eleman Çıkarma

Bir demetten eleman **çıkaramazsınız.** Bunun yerine yukarıdaki örnekte olduğu gibi önce listeye çevirip çıkarma işlemini yaptıktan sonra tekrar demete çevirebilirsiniz.

## 10.  **Demet** Kopyalamak ve Çoğaltmak

Elimizde olan bir demeti kopyalayarak çoğaltmak için kopyalanacak demeti belirterek yeni bir demet oluşturabiliriz.

```python
demet = ("a","b","c","d")

yenidemet = tuple(demet)

print(yenidemet) # ("a","b","c","d")
```

## 11. İki Farklı Demeti Birleştirmek

Birbirinden farklı veya aynı iki demeti birleştirmek için **+** operatörünü kullanabiliriz.

```python
demet1 = ("A","B","C") 
demet2 = ("D","E")

demet3 = demet1 + demet2

print(demet3) # ("A","B","C","D","E")
```

## 12. Bir Elemanın İndeksini Bulmak

Elimizdeki demetin bir elemanının demetteki indeksini bulmak için **index()** fonksiyonunu kullanabilirsiniz.

```python
demet = (14,36,2,95,43,0,66)

print(demet.index(95)) # 3
```

## 13. Bir Elemanın Varlığını Kontrol Etme

Demette bir elemanın var olup olmadığını kontrol etmek için **in** terimini kullanabiliriz.

```python
demet = ("A","B","C","D","E")

if "C" in demet: 
    print("Evet var!") 
else: 
    print("Hayır yok!")
    
# Evet var!
```


# # Python Kümeler

Python kümeler (sets) konusunu işliyoruz.

Python koleksiyonlar (diziler) altında yer alan **küme (set)** veri tipimiz *sıralanamayan* , değiştirilemeyen, *indekslenemeyen ve çoğul elemana izin vermeyen* bir veri tipidir. Süslü parantezlerle `{ }` oluşturulur.

```python
kume = {"elma","armut","çilek"}
```

{% hint style="warning" %}
Eleman olmadan sadece parantezlerle boş bir küme oluşturamazsınız.
{% endhint %}

```python
kume = {} # !!! Küme değil Sözlük veri tipi !!!

print(type(kume)) # <class 'dict'>
```

Kümeler aynı zamanda bir **set()** fonksiyonu ile de oluşturulabilir ve constructor yöntemiyle başlangıçta elemanları ayarlanabilir.

```python
kume = set()

kume = set(("Ankara","İstanbul","Kayseri"))
```

Oluşturduğumuz `küme` değişkenlerinin tipini kontrol edelim.

```python
print(type(kume)) # <class 'set'>
```

## 1. Küme Elemanlarına Erişim

Başlangıçta küme veri tipinin indekslenemeyeceğini söylemiştik. Bu nedenle bir indeks numarası belirterek herhangi bir elemana erişemezsiniz. Bunun yerine kümemizi **for** ile bir döngüye sokarak elemanları yazdırabiliriz.

```python
kume = {"elma","armut","çilek"}

for x in kume: 
    print(x)
```

Bu şekilde kümenin tüm elemanları x değeri üzerinden otomatik olarak listelenecek ve dizi elemanı bittiğinde döngü duracaktır.

## 2. Küme Eleman Sayısını Öğrenme

Elinizde olan bir kümenin eleman sayısını öğrenmek için **len()** fonksiyonunu kullanacağız.

```python
kume = {"a","b","c","d"}

print(len(kume)) #4
```

## 3. Bir Elemanın Varlığını Kontrol Etme

Kümede bir elemanın olup olmadığını kontrol etmek için in terimini kullanacağız. Eğer eleman varsa `True` , yoksa `False` değerini alırız.

```python
kume = {"a","b","c","d"}

print("b" in kume) # True 
print("f" in kume) # False
```

## 4. Küme Elemanının Değerini Değiştirme

{% hint style="warning" %}
Bir küme oluşturduğunuzda tıpkı demetlerde olduğu gibi artık elemanlarını değiştiremezsiniz.
{% endhint %}

## 5. Kümeye Yeni Eleman Ekleme

Oluşturduğumuz kümeye yeni bir eleman eklemek için **add()** fonksiyonunu kullanabilirsiniz.

```python
kume = {"a","b","c"}

kume.add("g")

print(kume) # {"b","c","g","a"}
```

Eğer tek seferde birden fazla eleman eklemek istiyorsanız **update()** fonksiyonunu kullanabilirsiniz.

```python
kume = {"a","b","c"}

kume.update(["x","y","z"])

print(kume) # {'y', 'c', 'b', 'x', 'z', 'a'}
```

Kümeye toplu eleman eklerken `update()` fonksiyonuna bir liste veya demet göndererek de ekleme işlemi yapabilirsiniz.

```python
kume = {"a","b","c"}
liste = ["x","y","z"] 
demet = (1,2,3)

kume.update(liste) 
kume.update(demet)

print(kume) # {1, 2, 3, 'y', 'a', 'x', 'c', 'b', 'z'}
```

{% hint style="info" %}
Küme elemanlarını ekrana yazdırdığınızda elemanların karışık bir halde geldiğini görürsünüz. Kümeler sıralanamayan bir veri tipi olduğu için her seferinde elemanların yeri değişir.
{% endhint %}

## 6. Kümeden Bir Eleman Çıkarmak

Kümemizden bir elemanı çıkarmak istediğimizde **remove()** veya **discard()** fonksiyonlarını kullanabiliriz. Her iki fonksiyonda işlevsellik olarak aynıdır.

```python
kume = {"a","b","c","d"}

kume.remove("b")

print(kume) # {'a', 'c', 'd'}
```

````python
```py kume = {"a","b","c","d"}

kume.discard("b")

print(kume) # {'d', 'c', 'a'}
````

{% hint style="info" %}
Her iki fonksiyonda işlevsel olarak aynı olmasına rağmen kümede olmayan bir elemanı kaldırmaya çalıştığınızda `remove()` fonksiyonu **hata mesajı verirken** , `discard()` fonksiyonu **hata mesajı vermez** .
{% endhint %}

Bu iki fonksiyonun dışında kümenin sondaki elemanını çıkarmak için **pop()** fonksiyonunu kullanabiliriz. Fakat kümeler **sıralanamayan** bir veri tipi olduğundan ve her seferinde elemanların yeri değişeceğinden hangi elemanın kümeden çıkarılacağı `pop()` fonksiyonunda **belli olmaz.**

```python
kume = {"a","b","c","d"}

kume.pop()

print(kume) # {'a', 'c', 'b'}
```

Kümedeki tüm elemanları çıkararak kümeyi temizlemek istediğinizde boş bir küme elde etmek için **clear()** fonksiyonunu kullanabilirsiniz.

```python
kume = {"a","b","c","d"}

kume.clear()

print(kume) # set()
```

## 7. Kümeyi Tamamen Silmek

Kümeden elemanları çıkarmak veya kümeyi temizlemek yerine isterseniz kümenizi tamamen silebilirsiniz. Bunun için **del** terimini kullanabilirsiniz. Fakat kümeyi sildikten sonra kullanmaya çalışırsanız hata alacaksınızdır.

```python
kume = {"a","b","c","d"}

del kume

print(kume) # !!! HATA VERİR !!!
```

## 8.  **Küme** Kopyalamak ve Çoğaltmak

Elimizde olan bir kümeyi kopyalayarak çoğaltmak için **copy()** fonksiyonunu kullanabilirsiniz.

```python
kume = {"a","b","c","d"}

yenikume = kume.copy()

print(yenikume) # {'a', 'd', 'b', 'c'}
```

Başka bir basit yöntemde kopyalanacak kümeyi belirterek yeni bir küme oluşturmaktır.

```python
kume = {"a","b","c","d"}

yenikume = set(kume)

print(yenikume) # {'b', 'a', 'c', 'd'}
```

## 11. İki Farklı Kümeyi Birleştirmek

Birbirinden farklı veya aynı iki kümeyi birleştirmek için **union()** ve **update()** fonksiyonlarını kullanabiliriz.

```python
kume1 = {"A","B","C"} 
kume2 = {"D","E"}

kume3 = kume1.union(kume2)

print(kume3) # {'E', 'C', 'D', 'B', 'A'}
```

```python
kume1 = {"A","B","C"} 
kume2 = {"D","E"}

kume1.update(kume2)

print(kume1) # {'D', 'C', 'E', 'B', 'A'}
```

{% hint style="info" %}
Küme veri tipindeki değişkenler aynı elemandan birden fazla bulunmasına izin vermeyeceği için kümeleri birleştirirken eğer aynı elemandan mevcutsa kümeden çıkarılacaktır.
{% endhint %}

```python
kume1 = {"A","B","C"} 
kume2 = {"A"}

kume3 = kume1.union(kume2)

print(kume3) # {"A","B","C"}
```

## 12. İki Farklı Kümenin Kesişimini Almak

Öncelikle elimizdeki iki kümenin kesişimi olup olmadığını öğrenmek için **isdisjoint()** fonksiyonunu kullanabiliriz. Eğer kümelerin kesişimi varsa **False** , yoksa **True** değeri döner.

```python
 kume1 = {"A","B","C"} 
 kume2 = {"A","D"} 
 kume3 = {"F","G"}
 
print(kume1.isdisjoint(kume2)) # False 
print(kume1.isdisjoint(kume3)) # True
```

İki kümenin kesişimini almak için **intersection()** fonksiyonunu kullanabiliriz.

```python
kume1 = {"A","B","C"} 
kume2 = {"A","D"}

kesisim= kume1.intersection(kume2)

print(kesisim) # {"A"}
```

Eğer iki kümenin kesişimini aldıktan sonra kümeyi bu kesişim elemanlarıyla güncellemek isterseniz **intersection\_update()** fonksiyonunu kullanabiliriz.

```python
kume1 = {"A","B","C"} 
kume2 = {"A","D"}

kume1.intersection_update(kume2)

print(kume1) # {"A"}
```

## 13. İki Farklı Kümenin Farkını Almak

Bir kümenin diğer kümeden farkını almak için **difference()** fonksiyonunu kullanabilirsiniz.

```python
kume1 = {"A","D","G"} 
kume2 = {"A","B","C","D"}

# kume1 in kume2 den farkı
fark = kume1.difference(kume2)

print(fark) # {"G"}
```

Eğer iki kümenin farkını aldıktan sonra kümeyi bu fark elemanlarıyla güncellemek isterseniz **difference\_update()** fonksiyonunu kullanabiliriz.

```python
kume1 = {"A","D","G"} 
kume2 = {"A","B","C","D"}

#kume1 in kume2 den farkı
kume1.difference_update(kume2)

print(kume1) # {"G"}
```

## 14. Kümenin Alt Küme Olup Olmadığını Kontrol Etme

Elimizdeki kümenin başka bir kümenin alt kümesi olup olmadığını kontrol etmek için **issubset()** fonksiyonunu kullanabiliriz.

```python
kume1 = {"A","B"} 
kume2 = {"A","B","C","D"}

print(kume1.issubset(kume2)) # True
```

## 14. Kümenin Üst Küme Olup Olmadığını Kontrol Etme

Elimizdeki kümenin başka bir kümenin üst kümesi olup olmadığını kontrol etmek için **issuperset()** fonksiyonunu kullanabiliriz.

```python
kume1 = {"A","B"} 
kume2 = {"A","B","C","D"}

print(kume2.issuperset(kume1)) # True
```


# # Python Kısıtlanmış Kümeler

Python kısıtlanmış kümeler (frozensets) konusunu işliyoruz.

Python koleksiyonlar (diziler) altında yer alan **küme (set)** veri tipimizi bir önceki derste anlatmıştık. **Kısıtlanmış küme (frozenset)** ise küme değişkeniyle neredeyse birebir aynıdır. Tek farkı eleman ekleme, çıkarma, küme temizleme gibi fonksiyonlar yoktur.

```python
kume = frozenset()

kume = frozenset(("Ankara","İstanbul","Kayseri"))
```

Oluşturduğumuz `küme` değişkenlerinin tipini kontrol edelim.

```python
print(type(kume)) # <class 'frozenset'>
```

Kısıtlanmış kümelerde kullanabileceğiniz fonksiyonlar şunlardır. İlgili fonksiyonların nasıl kullanılacağını bir önceki dersten görebilirsiniz;&#x20;

* copy()
* difference()
* intersection()
* isdisjoint()
* issubset()
* issuperset()
* symmetric\_difference()
* union()


# # Python Sözlükler

Python sözlükler (dictionaries) konusunu işliyoruz.

Python koleksiyonlar (diziler) altında yer alan **sözlük (dict)** veri tipimiz *değiştirilebilen* , *indekslenebilen, çoğul elemana izin veren* ama *sıralanamayan* bir veri tipidir. Süslü parantezlerle `{ }` oluşturulur.

```python
sozluk = {}
```

Süslü parantezlere oluşturulan sözlükler, en başta elemanlarla birlikte de oluşturulabilirler.

```python
sozluk = {
         "marka" : "BMW",
         "model" : "i8",
         "yil"   : 2019
         }
```

Aynı zamanda bir sözlük **dict()** fonksiyonu ile de oluşturulabilir ve constructor yöntemiyle başlangıçta elemanları ayarlanabilir.

```python
sozluk = dict()

sozluk = dict(sehir = "Ankara", plaka = 6)
```

Daha gelişmiş bir kullanım olan **fromkeys()** fonksiyonu ile de demetleri kullanarak sözlük oluşturabilirsiniz ve tüm anahtar değerlere aynı anda bir değer atayabilirsiniz.

```python
x = ('anahtar1', 'anahtar2', 'anahtar3') 
y = 0

sozluk = dict.fromkeys(x, y)

print(sozluk) # {'anahtar2': 0, 'anahtar3': 0, 'anahtar1': 0}
```

Oluşturduğumuz `sozluk` değişkenlerinin tipini kontrol edelim.

```python
print(type(sozluk)) # <class 'dist'>
```

## 1. Sözlük Elemanlarına Erişim

Python programlama dilinde elinizdeki bir sözlüğün elemanlarına ulaşabilmek için verinin `key` yani **anahtar** kısmını kullanabilirsiniz. Aşağıdaki örnekle anahtarları nasıl kullanacağınızı gösterelim.

```python
sozluk = {
         "marka" : "BMW",
         "model" : "i8",
         "yil"   : 2019
         }
         
yil = sozluk["yil"]

print(yil) # 2019
```

Aynı erişim yöntemini **get()** fonksiyonla da kullanabilirsiniz.

```python
sozluk = {
         "marka" : "BMW",
         "model" : "i8",
         "yil"   : 2019
         }

yil = sozluk.get("yil")

print(yil)         # 2019
```

## 2. Sözlük Elemanlarını Sıralayarak Ekrana Yazdırma

Yeri geldiğinde sözlük elemanlarınızı ekrana sırasıyla yazdırmak, elemanlar üzerinde sırasıyla işlem yapmak isteyebilirsiniz. Bunun için iki yöntemimiz var ve ilkiyle hemen başlayalım.

```python
sozluk = {
         "ulke" : "Türkiye",
         "sehir" : "Ankara",
         "ilce"   : "Yenimahalle"
         }


for x in sozluk:
    print("Anahtar: " + x + " -- " + "Değer: " + sozluk[x])

# Anahtar: ulke -- Değer: Türkiye
# Anahtar: sehir -- Değer: Ankara
# Anahtar: ilce -- Değer: Yenimahalle
```

Bu örnekte sözlükteki tüm anahtar kelimeleri x değeri üzerinden otomatik olarak listeledik ve bu anahtar kelimeye denk gelen değeri çektik. Şimdi ise aynı örneğimizdeki döngümüzü **items()** ve **values()** fonksiyonlarını kullanarak döndüreceğiz. İlk olarak **items()** fonksiyonu ile başlarsak `anahtar` ve `değerlerin` sırasıyla `x` ve `y` değişkenine atandığını görebiliriz.

```python
sozluk = {
         "ulke" : "Türkiye",
         "sehir" : "Ankara",
         "ilce"   : "Yenimahalle"
         }


for x,y in sozluk.items():
    print("Anahtar: " + x + " -- " + "Değer: " + y)

# Anahtar: ulke -- Değer: Türkiye
# Anahtar: sehir -- Değer: Ankara
# Anahtar: ilce -- Değer: Yenimahalle
```

Sadece **values()** fonksiyonunu kullandığımızda ise döngümüzde yalnızca değerlerin döndüğünü görebiliriz.

```python
sozluk = {
         "ulke" : "Türkiye",
         "sehir" : "Ankara",
         "ilce"   : "Yenimahalle"
         }


for x in sozluk.values():
    print(x)

# Türkiye
# Ankara
# Yenimahalle
```

{% hint style="info" %}
Sözlük elemanlarını ekrana yazdırdığınızda elemanların karışık bir halde geldiğini görürsünüz. Sözlükler sıralanamayan bir veri tipi olduğu için her seferinde elemanların yeri değişir.
{% endhint %}

## 3. Sözlük Eleman Sayısını Öğrenme

Elinizde olan bir sözlüğün eleman sayısını öğrenmek için **len()** fonksiyonunu kullanacağız.

```python
sozluk = {
         "marka" : "BMW",
         "model" : "i8",
         "yil"   : 2019
         }

print(len(sozluk))    #3
```

## 4. Bir Elemanın Varlığını Kontrol Etme

Sözlükte bir **anahtarın** olup olmadığını kontrol etmek için `in` terimini kullanacağız. Eğer eleman varsa `True` , yoksa `False` değerini alırız.

```python
sozluk = {
         "marka" : "BMW",
         "model" : "i8",
         "yil"   : 2019
         }

print("model" in sozluk)    # True
print("i8" in sozluk)    # False
```

## 5. Sözlüğe Yeni Eleman Ekleme

Oluşturduğumuz sözlüğe yeni bir eleman eklemek için direkt yeni anahtar-değer çiftini kullanabilirsiniz.

```python
sozluk = {
         "marka" : "BMW",
         "model" : "i8",
         }

sozluk["yil"] = 2019

print(sozluk)       # {'yil': 2019, 'marka': 'BMW', 'model': 'i8'}
```

## 6. Sözlükten Bir Eleman Çıkarmak

Sözlükten anahtar kelimeyi belirterek bir eleman çıkarmak için **pop()** fonksiyonunu kullanabiliriz.

```python
sozluk = {
         "marka" : "BMW",
         "model" : "i8",
         "yil"   : 2019
         }

sozluk.pop("yil")

print(sozluk)       # {'marka': 'BMW', 'model': 'i8'}
```

Sözlük veri tipinde elemanlar sıralanamadığı için sözlükten rastgele bir eleman çıkarmak için **popitem()** fonksiyonunu kullanabiliriz.

```python
sozluk = {
         "marka" : "BMW",
         "model" : "i8",
         "yil"   : 2019
         }

sozluk.popitem()

print(sozluk)       # {'model': 'i8', 'yil': 2019}
```

Eğer tek tek eleman çıkarmakla uğraşmayıp tüm elemanları sözlükten çıkarmak, sözlüğü temizlemek istiyorsanız **clear()** fonksiyonunu kullanabiliriz.

```python
sozluk = {
         "marka" : "BMW",
         "model" : "i8",
         "yil"   : 2019
         }

sozluk.clear()

print(sozluk)       # {}
```

## 7. Sözlüğü Tamamen Silmek

Sözlükten elemanları çıkarmak veya sözlüğü temizlemek yerine isterseniz sözlüğü tamamen silebilirsiniz. Bunun için **del** terimini kullanabilirsiniz. Fakat sözlüğü sildikten sonra kullanmaya çalışırsanız hata alacaksınızdır.

```python
sozluk = {
         "marka" : "BMW",
         "model" : "i8",
         "yil"   : 2019
         }

del sozluk

print(sozluk)        # !!! HATA VERİR !!!
```

## 8.  **Sözlük** Kopyalamak ve Çoğaltmak

Elimizde olan bir sözlüğü kopyalayarak çoğaltmak için **copy()** fonksiyonunu kullanabilirsiniz.

```python
sozluk = {
         "sehir" : "Ankara",
         "plaka" : 6
         }

yenisozluk = sozluk.copy()

print(yenisozluk)     # {'sehir': 'Ankara', 'plaka': 6}
```

Başka bir basit yöntemde kopyalanacak sözlüğü belirterek yeni bir sözlük oluşturmaktır.

```python
sozluk = {
         "sehir" : "Ankara",
         "plaka" : 6
         }

yenisozluk = dict(sozluk)

print(yenisozluk)     # {'sehir': 'Ankara', 'plaka': 6}
```

## 9. İç İçe Sözlük Oluşturma

Dersimizin başında nasıl sözlük oluşturabileceğimizi gördük. Şimdi ise sözlük içinde sözlük, yani iç içe sözlük kullanarak nasıl sözlük değişkeni oluşturabileceğimizi göstereceğiz.

```python
sozluk = {
          "sehir1" : {
                      "sehir" : "Ankara",
                      "plaka" : 6
                     },
          "sehir2" : {
                      "sehir" : "İstanbul",
                      "plaka" : 34
                     },
         "sehir3" : {
                      "sehir" : "Kayseri",
                      "plaka" : 38
                     },
         }
```

Eğer bu kullanım biraz karışık gelmişse tüm sözlükleri ayrı ayrı oluşturup en son birleştirebilirsiniz.

```python
sehir1 = {
           "sehir" : "Ankara",
           "plaka" : 6
         }

sehir2 = {
           "sehir" : "İstanbul",
           "plaka" : 34
         }

sehir3 = {
           "sehir" : "Kayseri",
           "plaka" : 38
         }

sozluk = {
           "sehir1" : sehir1,
           "sehir2" : sehir2,
           "sehir3" : sehir3
         }
```


# # Python If Else Elif

Python koşul durumları (if else elif) konusunu işliyoruz.

Bilgisayar teknolojilerinin temelinde nasıl ki 0 ve 1 durumları varsa programlama dillerinin de temelinde algoritmaları oluşturan if ve else durumları vardır. Bu dersimizde de önemli bir aşama olan if..else konusunu anlatacağız. Koşul ifadeleri programımızda durumları kontrol etmemizi ve programlamanın seyrini değiştirmeye yarar. **if** , **else** ve **elif** terimleriyle mantıksal ifadeleri kullanarak bir durumun koşulu sağlaması durumunda çalışmasını gerçekleştirebiliriz.

```python
a = 25 
b = 50

if b > a: 
    print("b büyüktür a dan")
```

Örnekte gördüğünüz gibi eğer `b > a` koşulu doğruysa program if durumunun içine girer ve ekrana metni yazdırır.

{% hint style="info" %}
Koşul durumlarında **==** , **!=** , **<** , **<=** , **>** , **>=** ifadelerini kullanabilirsiniz.
{% endhint %}

Eğer **if** koşulunun gerçekleşmediği durumda başka bir durumun gerçekleşmesini istiyorsak bunu **else** terimi ile gerçekleştirebiliriz.

```python
sayi = 3

if sayi%2 == 0:
    print(str(sayi) + " çift sayıdır")
else:
    print(str(sayi) + " tek sayıdır")
```

Bu örnekte 3 sayısının tek mi çift sayı olduğunu kontrol ediyoruz. Eğer sayımız çift ise if durumu, değilse else durumu çalışacaktır. Programımızda yeri geldiğinde birden fazla durumu kontrol etmek durumunda kalabiliriz. Bunun içinde Python programlama dilinde **elif** terimi devreye girer.

```python
yas = 65

if yas < 18:
    print("Ergensiniz")
elif yas >= 18 and yas < 66:
    print("Gençsiniz")
elif yas >= 66 and yas < 79:
    print("Orta yaşlısınız")
elif yas >= 80 and yas < 100:
    print("Yaşlısınız")
else:
    print("Yaş grubunuzu belirleyemedik!")
```

Örnekte olduğu gibi artık sadece **if** ve **else** ile kalmadık ve ara durum koşullarını da **elif** ile kullandık.

## 1. Tek Satırda If Else Elif Kullanımı

Yukarıda gördüğümüz örnekleri isterseniz tek satır ile de aradan çıkarabilirsiniz. Programınızı daha sonradan rahatça okuyabilmeniz için her ne kadar bu yöntemi tavsiye etmesek bile öğrenmenizde fayda var.

```python
a = 20
b = 10

if a > b: print("a büyüktür b den")
```

Tek **if** kullanımını gördükten sonra şimdi de **if** ve **else** durumunu görelim.

```python
a = 10

print("Çift sayı") if a%2 == 0 else print("Tek sayı")
```

İşi biraz daha zorlaştırıp daha fazla koşulu işin içine katabiliriz.

```python
yas = 10

print("Genç") if yas > 18 else print("Bebek") if yas < 5 else print("Ergen")
```

## 2. İç İçe If Else Kullanımı

Koşullarınızı yazarken iç içe if ve else koşullarınızı yazarak daha detaylı koşul durumları oluşturabiliriz.

```python
x = 41

if x > 10:
  print("Sayı ondan büyük")
  if x > 20:
    print("Sayı yirmiden büyük")
  else:
    print("Sayı yirmiden küçük")
```

## 3.  pass Terimi Kullanımı

Yukarıdaki örneklerinde hepsinde koşullarımız gerçekleştiğinde bir komut çalıştırdık. Fakat bazen koşul gerçekleştiğinde hiçbir şey yapmak istemeyebilirsiniz. Örneğin bir hata durumunu kontrol edebilir ve hata olmaması durumunda programda sadece ilerlemek işimizi görebilir. İşte bu durumlar için **pass** terimi devreye giriyor.

```python
kontrol = 1

if kontrol == 0:
    print("Hata Var!")
else:
    pass
```

Bu örnekte programımız else koşulu içine girdi ve **pass** terimini gördüğü için herhangi bir komut çalıştırmadan ve hata vermeden devam ederek **if-else** bloku içinden çıktı.


# # Python Döngüler

Python döngüler (loops) konusunu işliyoruz.

Python programlama dilinde kullanabileceğimiz iki tür döngü çeşidi vardır. Bu döngüler şunlardır;

* **for**
* **while**

Bu döngüler sayesinde programımızda bir dizi elemanları boyunca veya belirlediğimiz iki değer arasında bir süreç oluşturup programımızın tekrarlı çalışmasını sağlayabiliriz. İlk dersimiz olan **for** döngüleri ile başlayalım.


# # Python While Döngüsü

Python döngüler (while) konusunu işliyoruz.

Python programlama dilinde **for** döngüsü ile diziler, stringler ve aralıklar üzerinde döngümüzü nasıl işleteceğimizi bir önceki derste görmüştük. Şimdi ise bir koşul aracılığıyla nasıl bir döngü oluşturacağımızı **while** kullanımı ile öğreneceğiz. Şimdi basit bir koşul oluşturarak ilk **while** döngümüzü yazalım.

```python
i = 1

while i < 4:
  print(i)
  i += 1

# 1
# 2
# 3
```

Örnekte gördüğünüz gibi **while** ile yazdığımız döngüde **i** değeri **4** ten küçük olduğu sürece döngümüz işlemeye devam edecektir.

{% hint style="warning" %}
Bu örnekte olduğu gibi koşulda kontrol ettiğiniz **i** değerini her döngü sonunda artırmayı unutmayınız. Aksi takdirde sonsuz döngü oluşur ve hata alırsınız.
{% endhint %}

## 1. While Döngüsünü Durdurma

Döngümüz ilerlerken istediğimiz bir durumda durdurabilmek için **break** komutunu kullanırız. Python **break** komutunu gördüğünde döngüyü durdurarak döngüden çıkar.

```python
i = 1

while i < 6:
  print(i)
  if i == 2:
    break
  i += 1

# 1
# 2
```

## 2. While Döngüsünde Atlama Yapmak

Döngümüzü bir koşul ile durdurabileceğimizi gördük. Şimdi ise yine bir koşul ile döngüde ki o durumu atlayabiliriz ve döngünün diğer aşamasına geçebiliriz. Bunun için **continue** terimini kullanabiliriz.

```python
i = 0

while i < 3:
  i += 1
  if i == 2:
    continue
  print(i)

# 1
# 3
```

## 3. Döngü Bitince Komut Çalıştırmak

Şimdiye kadar döngüyü durdurmayı, döngüden çıkmayı ve atlamayı gördük. Şimdi ise döngümüz bittiğinde nasıl komut çalıştıracağımızı göreceğiz.

```python
i = 1

while i < 3:
    print(i)
    i += 1
else:
    print("Döngü bitti!")

# 1
# 2
# Döngü bitti!
```

Koşul durumlarında kullandığımız **else** ifadesi, döngülerde de kullanılarak döngünün bittiği durumu tanımlar.


# # Python For Döngüsü

Python döngüler (for) konusunu işliyoruz.

Python programlama dilinde bir liste, demet, sözlük, küme, string veya belirlediğiniz iki sayı arasında döngü oluşturmak istediğinizde **for** terimini kullanırsınız. Programlama da önemli bir yeri olan **for** için örnek kullanımları hemen görelim. Öncelikle bir **string** için döngü oluşturalım.

```python
isim = "Blog"

for x in isim:
    print(x)

# B
# l
# o
# g
```

Örnekte gördüğünüz gibi isim değişkenimizi for döngüsüne sokarak her bir karakter boyunca döngümüz devam eder. Bu döngü esnasında karakterler **x** değerine atanır. Şimdi de **liste** üzerinde bir örnek görelim.

```python
liste = ["Ankara","İstanbul","Kayseri"]

for sehir in liste:
    print(sehir)

# Ankara
# İstanbul
# Kayseri
```

## 1. İki Sayı Arasında Döngü Oluşturmak

Nasıl ki listelerimiz, demetlerimiz üzerinde rahatça döngümüzü oynatabiliyorsak, belirlediğimiz iki sayı arasında da döngü ayarlayabiliriz. Örneğin bir döngüyü sadece 5 kere döndürmek istediğinizde **range()** fonksiyonunu kulanabilirsiniz:

```python
for i in range(1,6):
    print("♥"*i)

# ♥
# ♥♥
# ♥♥♥
# ♥♥♥♥
# ♥♥♥♥♥
```

Unutmayınız, **range(x,y)** fonksiyonu **x** sayısından başlar, **y** sayısına kadar sayı üretir. **y** sayısı dahil değildir. Sadece **range(x)** fonksiyonunu kullanırsak döngü **0** ve **x** arasında döner. **x** yine dahil değildir.

```python
for i in range(3):
    print("Sayı: " + str(i))

# Sayı: 0
# Sayı: 1
# Sayı: 2
```

Dahası, **range(x,y,z)** fonksiyonu ile **x** ve **y** arasındaki sayıları yazdırırken sayıların kaçar kaçar büyüyeceğini **z** ile belli edebiliriz.

```python
for i in range(1,15,3):
    print(i)

# 1
# 4
# 7
# 10
# 13
```

## 2. For Döngüsünü Durdurma

Döngümüz ilerlerken istediğimiz bir durumda durdurabilmek için **break** komutunu kullanırız. Python **break** komutunu gördüğünde döngüyü durdurarak döngüden çıkar.

```python
for i in range(10):
    if i == 4:
        break
    print(i)

# 0
# 1
# 2
# 3
```

## 3. For Döngüsünde Atlama Yapmak

Döngümüzü bir koşul ile durdurabileceğimizi gördük. Şimdi ise yine bir koşul ile döngüde ki o durumu atlayabiliriz ve döngünün diğer aşamasına geçebiliriz. Bunun için **continue** terimini kullanabiliriz.

```python
for i in range(10):
    if i % 2 == 0:
        continue
    print(i)

# 1
# 3
# 5
# 7
# 9
```

Örnekte çift sayıları atlayarak sadece tek sayıları ekrana yazdırdık.

## 4. Boş Döngü Döndürmek

Bazı durumlarda döngüyü sadece döndürmek ve herhangi bir işlem, ekran çıktısı yapmak istemeyebilirsiniz. Bu durumlar içinde **pass** terimini rahatlıkla kullanabilirsiniz.

```python
for i in [0, 1, 2]: 
    pass
```

Eğer boş döngülerde **pass** terimini kullanmazsanız hata alırsınız.

## 5. Döngü Bitince Komut Çalıştırmak

Şimdiye kadar döngüyü durdurmayı, döngüden çıkmayı ve atlamayı gördük. Şimdi ise döngümüz bittiğinde nasıl komut çalıştıracağımızı göreceğiz.

```python
for sayi in range(2):
    print(sayi)
else:
    print("Döngü bitti!")

# 0
# 1
# Döngü bitti!
```

## Döngü bitti!

Koşul durumlarında kullandığımız **else** ifadesi, döngülerde de kullanılarak döngünün bittiği durumu tanımlar.


# # Python Fonksiyonlar

Python fonksiyonlar (functions) konusunu işliyoruz.

Fonksiyonlar, sadece çağrıldıklarında çalışan kod bloklarıdır. Bir fonksiyon ile tanımladığınız belirli komutlarınız, yeri geldiğinde çağrılarak, parametreler gönderilerek kullanılır ve istenilirse size bir değer döndürür.

## 1. Fonksiyon Oluşturmak ve Çağırmak

Python programlama dilinde bir program oluşturabilmek için **def** terimini kullanırız ve ardından fonksiyon ismini yazarız.

```python
def ornekFonksiyon(): 
    print("Merhaba Dünya!")
```

Oluşturduğumuz bir fonksiyonu programımızın istediğimiz yerinde çağırabiliriz. Bunun için sadece fonksiyon ismini belirtmemiz yeterlidir.

```python
ornekFonksiyon()
```

## 2. Fonksiyon Parametreleri

Oluşturduğumuz fonksiyona parametre göndererek işleme sokmak istiyorsak, fonksiyonumuzu oluştururken parantezlerin arasında bu parametreleri belirtmeli ve fonksiyonu çağırırken ilgili parametre değerleri ile çağırmalıyız.

```python
def selamVer(isim,yas): 
    print("Merhaba, {} {} yaşındadır".format(isim,yas))

selamVer("Yunus",24)

# Merhaba, Yunus 24 yaşındadır
```

Örnekte gördüğünüz gibi fonksiyona iki adet parametre alacağını söyledik ve fonksiyonu çağırırken bu iki parametrenin de değerini gönderdik. Fonksiyon da gelen bu parametreleri ilgili yerlere otomatik olarak yerleştirdi. Bir örnek daha yapalım.

```python
def usAlma(x): 
    print(x**2)

usAlma(7) # 49
```

{% hint style="info" %}
Fonksiyonlarınız da istediğiniz kadar parametre kullanabilirsiniz fakat ilgili fonksiyonu çağırırken tüm parametrelere değer atadığınızdan emin olmalısınız.
{% endhint %}

```python
def toplama(x,y): 
    print(x+y)
    
toplama(25) # !! HATA VERİR (eksik parametre değeri) !!
```

## 3. Öntanımlı Parametre İle Fonksiyon Oluşturmak

Fonksiyonlarımızı oluştururken alacağı parametrelerin değerlerini öntanımlı olarak belirleyebiliriz. Bu sayede kullanıcı eğer parametrenin değerini göndermezse biz bu parametreye bir öntanımlı değer atayabiliriz.

```python
def dogumYeri(sehir="Bilinmiyor"):
    print("Doğum yeri: " + sehir)

dogumYeri("Ankara")      # Doğum yeri: Ankara
dogumYeri("İstanbul")    # Doğum yeri: İstanbul
dogumYeri()              # Doğum yeri: Bilinmiyor
```

## 4. Belirsiz Sayıda Fonksiyon Parametresi

Yukarıdaki örneklerde gönderilecek parametre adedini belirledik ve fonksiyon çağırırken belirlenen parametre adedince değer gönderdik. Peki yazdığımız fonksiyon onlarca,yüzlerce parametreye ihtiyaç duyduğunda tüm parametreleri tek tek fonksiyon oluştururken belirtecek miyiz? Tabiki de hayır Python programlama dilinde eğer belirsiz sayıda değişken ile fonksiyon oluşturacaksanız **\*** işaretiyle parametre adı belirlemelisiniz. Bu sayede tanımladığınız parametre bir demete dönüşecek ve gönderdiğiniz tüm değerler bu demete eleman olarak eklenecektir.

```python
def meyveler(*meyve):
    print(meyve[0])
    print(meyve[1])

meyveler("elma","muz","çilek","kavun")

# elma
# muz
```

## 5. Fonksiyon Dönüş Değeri Belirleme

Fonksiyonlarımızın çağrıldıkları zaman çalıştıklarını artık öğrendik. Ayrıca bu fonksiyonlar ile ekrana çıktı verebildiğimizi de yukarıdaki örneklerde gördünüz. Şimdi ise oluşturduğumuz fonksiyonlara **return** ile dönüş değeri döndürmesini söyleyeceğiz ve fonksiyonlarımızı çalışması için çağırdığımızda bize bir değer döndürecek.

```python
def carpma(x,y): 
    return x*y
    
sonuc = carpma(7,5)

print(sonuc) # 35
```

Bu basit örneğimizde fonksiyonumuzun çarpma işlemini yaparak bize **return** ile sonucu döndürmesini istedik. Böylece fonksiyon sonucunu bir değere atayarak veya direkt print ile ekrana yazdırarak işlem sonucumuzu öğrenmiş olduk.

```python
def selamVer(): 
    return "Merhaba!"
    
print(selamVer()) # Merhaba!
```

## 6. Boş Fonksiyon Oluşturmak

Herhangi bir sebep yüzünden boş fonksiyon oluşturmak istediğinizde hata almamak için **pass** terimini kullanabilirsiniz.

```python
def dahaSonra(): 
    pass
```

## 7. Yinelemeli Fonksiyonlar

Yinelemeli (recursive) fonksiyonlar kendi kendini çağıran fonksiyonlardır. Bir fonksiyonu yinelemeli hale getirmek için herhangi bir terim kullanmamıza gerek yoktur. Fonksiyonu oluştururken içeride yine aynı fonksiyonu çağırarak yinelemeli hale getirebilirsiniz. Yinelemeli fonksiyonlar birçok alanda kullanılır ve işlem kolaylığı sağlar. Daha çok matematiksel hesaplamalarda tercih edilmesine rağmen kendi işlevlerinizi de yinelemeli olarak yerine getirebilirsiniz.

```python
def faktoriyel(x):

    if x == 1:
        return 1
    else:
        return x * faktoriyel(x-1)

sonuc = faktoriyel(5)

print(sonuc)    # 120
```

Örneğimizde basit bir faktoriyel hesaplama fonksiyonunu yinelemeli bir fonksiyon ile yazdık. Burada 5 sayısının faktoriyelini hesaplarken (5\*4\*3\*2\*1) sonucunu alabilmek için fonksiyonumuzun içinde her seferinde sayının bir küçüğünü tekrardan fonksiyon ile çağırarak çarptık ve en son 1 sayısına geldiğimizde fonksiyonumuzu sonlandırdık. Sizde kendinize yinelemeli fonksiyonlarla yazacağınız örnekler bularak programlama da pratiklik kazanabilirsiniz.


# # Python Lambda Fonksiyonu

Python lambda fonksiyonu (lambda functions) konusunu işliyoruz.

Python programlama dilinde fonksiyonlar konusunu bir önceki derste işledik. Şimdi ise fonksiyonları tek satırlık ifadelerle yazmamızı ve bize pratiklik sağlayan bir konu olan **lambda** fonksiyonlarını işleyeceğiz. Öncelikle lambda fonksiyonlarının syntax ını öğrenelim.

```python
lambda p1, p2: komut
```


# # Python Sınıflar

Python sınıflar (class) konusunu işliyoruz.

Python nesne yönelimli bir dildir ve gücünü bu sayede katlayarak bizlere ulaşır. Python programlama dilinde neredeyse her şey bir objedir. Peki sınıf ve obje nedir?

Programlama dillerinde **sınıf** ; içerisinde değişken ve fonksiyonları barındıran, yeri geldiğinde bunları kullandıran taslaklardır. Bir örnek vererek bu tanımı güçlendirelim.

En klasik örnek üzerinden yürürsek, bir okulunuz var ve okulda şubelere, her şubede ise onlarca öğrenciye sahipsiniz. Bu elemanlarla bir yazılım hazırlayacak olursak farketmişsinizdir ki şimdiye kadar gördüğümüz dersler bu konuda yetersiz kalacaktır. Çünkü binlerce öğrenci için binlerce değişken oluşturmamız mı gerekecek? Veya her öğrencinin farklı özelliklerini, şube adını, veli bilgilerini vs nerede nasıl tutacağız? Ortada büyük bir kaos var maalesef Elimizde ki problemin kaynağını öğrendik. Büyük verilerle oynarken her üye ve bu üyenin özellikleri için bir değişken oluşturursak binlerce değişkenle işin içinden çıkamayız. İşte tam burada da Python sınıf kullanımı imdadımıza yetişiyor. Eğer elimizde bir sınıfın ve öğrencinin nasıl olacağına dair bir taslak olursa, bu sınıflardan istediğimiz kadar elemanı rahatlıkla oluşturabilir ve sınıfın özelliklerini **üyelere yani objelere (nesnelere)** atayabiliriz. Görselde gördüğünüz üzere basit bir öğrenci taslağı hazırladık. Bu taslakta öğrencilerin alacağı değişken özelliklerini ve sahip olacakları fonksiyonları oluşturduk. Artık bu taslağa bağlı olarak istediğimiz kadar öğrenci yani nesne (obje) oluşturabiliriz.

## 1. Class Oluşturma

Python programlama dilinde bir sınıf oluşturabilmek için **class** terimini kullanırız.

```python
class ogrenci: 
    pass
```

Evet işte bu kadar. En temel haliyle elimizde artık bir sınıfımız var. Şimdi ise tüm öğrencilerde olacak ortak sınıf değişkenlerimizi tanımlayalım.

```python
class ogrenci: 
    isim = None 
    yas = None 
    sinif = None 
    devamsizlik = 0
```

Burada ise sınıf değişkenlerimizi oluşturduk fakat bunları yaparken çoğu değişkene herhangi bir değer atamadık. İsteseydik burada `devamsizlik` değişkeninde olduğu gibi öntanımlı bir değer atayarak bu sınıf değişkenlerinin ilk başta bir değere sahip olmasını sağlayabilirdik. Sırada sınıfımıza fonksiyonel yetenek kazandıracak methodları ekleme var.

```python
class ogrenci: 
    isim = None 
    yas = None
    
    def selamVer():
        print("Merhaba")
```

Artık çok basit bir sınıfımız olduğuna göre ilk testlerimizi yapalım.

## 2. Class Değişken ve Fonksiyonlarını Çalıştırma

İlk başlığımızda basit bir sınıfın nasıl oluşturulduğunu gördük. Nesne ve diğer sınıf yeteneklerine ulaşmadan önce basit yoldan sınıf elemanlarına nasıl erişebileceğimizi görelim. Elimizdeki bir sınıfın değişken ve fonksiyonlarına ulaşmak için sınıf adını yazdıktan sonra ulaşmak istediğimiz elementi seçmemiz gerekiyor.

```python
class ogrenci:
    isim = "-"
    yas = 10

    def selamVer():
        print("Merhaba")

print(ogrenci.isim)    # -
print(ogrenci.yas)     # 10
ogrenci.selamVer()     # Merhaba
```

Örnekte gördüğünüz gibi basit bir sınıfın elemanlarına basit bir yöntemle ulaştık. Şimdi ise sınıf `devamsizlik` değişkenini her çağırdığımızda bir artıran fonksiyonu yazalım.

```python
class ogrenci:
    isim = "-"
    devamsizlik = 0

    def devamsizlikEkle():
        ogrenci.devamsizlik += 1

print(ogrenci.devamsizlik)    # 0

ogrenci.devamsizlikEkle()     # Merhaba

print(ogrenci.devamsizlik)     # 1
```

Buradaki örnekte ise sınıf `devamsizlik` değişkenimizin sınıf dışından nasıl artırılacağını gördük.

Peki bu yöntemleri normal bir fonksiyondan ayıran özellikler nerede? Özellikle de bu taslağı farklı farklı nesneler üzerinde kullanacağımız objeler nerede? Sanki bir şeyler eksik gibi Şimdiye kadar gördüğümüz kısımlar bir sınıfın en temelidir ve iskeletinin nasıl olduğunu anlatır. Fakat bu haliyle sınıfları sınıf gibi kullanamazsınız. Çünkü elimizde halen objeler yok ve yaptığımız her işlem sınıfın kendi değişkenleri üzerinde gerçekleşti. Öyleyse şimdi hemen nesne kullanımını öğrenelim ve asıl sınıf dersine başlayalım.

## 3. Nesne (Obje) Oluşturma

Sınıflar (classes) konusunun kullanılmasının asıl amacı değişken yığınlarıyla uğraşmayıp bir taslak oluşturmak ve bu taslağı tüm değişkenlerimize uygulayabilmektir. Böylece hem bir kargaşadan kurtuluruz hemde daha profesyonel bir kod yazabiliriz. Python programlama dilinde yazdığınız bir sınıftan nesneler oluşturmak için değişkeninize sınıf ismini fonksiyon olarak atamalısınız. Örnekleri hemen görelim.

```python
class ogrenci:
    isim = None
    yas = None

o1 = ogrenci()
o2 = ogrenci()
```

Artık elimizde `ogrenci` sınıfından türemiş iki adet nesnemiz (objemiz) oldu. Öyleyse bu nesnelerimiz için sınıfımızın isim değişkenine değer atamakla başlayalım.

```python
class ogrenci:
    isim = None
    yas = None

o1 = ogrenci()
o2 = ogrenci()

o1.isim = "Yunus"
o2.isim = "İsmet"

print(o1.isim)    # Yunus
print(o2.isim)    # İsmet
```

Nesnelerimizle ilk temasımızı kurduk. Artık istediğiniz sayıda obje oluşturabilirsiniz. Hatta basit bir fonksiyonla her öğrencinin selam vermesini de sağlayabiliriz.

```python
class ogrenci:
    isim = None
    yas = None
    devamsizlik = 0

    def selamVer():
        print("Merhaba !")

o1 = ogrenci()
o2 = ogrenci()

o1.selamVer()    # Merhaba !
o2.selamVer()    # Merhaba !
```

Bu örnekte her öğrencinin kendi ismiyle selam vermesini istersek peki nasıl yapabiliriz?

```python
class ogrenci:
    isim = "---"
    devamsizlik = 0

    def selamVer():
        print("Merhaba, ben " + ogrenci.isim)

o1 = ogrenci()
o1.isim = "Yunus"


ogrenci.selamVer()       # Merhaba, ben ---
o1.selamVer()            # !!!!!! HATA !!!!!!
```

Bu da nedir? Neden böyle bir hata aldık ki? Peki şimdi sınıfımıza devamsızlık değişkenini ve her çağrıldığında öğrenci nesnesinin devamsızlık sayısını bir artıracak fonksiyonu yazsak yine hata alır mıyız acaba?

```python
class ogrenci:
    isim = None
    devamsizlik = 0

    def devamsizlikEkle():
        ogrenci.devamsizlik += 1

o1 = ogrenci()
print(o1.devamsizlik)    # 0

ogrenci.devamsizlikEkle()
print(o1.devamsizlik)    # 1

o1.devamsizlikEkle()     # !!!!!! HATA !!!!!!
```

Sanırım bir terslik var. Objelerimiz sınıf değişkenlerine erişebiliyor ama onları sınıf değişkenleri üzerinden değiştiremiyor Şimdi bunun sebebini yeni başlığımız altında öğrenelim. (Cevabı konu sonunda)

## 5. **init**() Fonksiyonu ve self Terimi Kullanımı

Şu ana kadar sınıfları nasıl oluşturup kullanacağımızı ve bu **sınıflara ait değişkenleri** nasıl tanımlayacağımızı gördük. Bu cümledeki sınıflara ait değişkenler kısmı önemlidir çünkü oluşturduğumuz tüm değişkenler nesnelerimize ait değil, sınıfımıza aittir. Hatırlayalım hemen;

```python
class ogrenci: 
    isim = "-"
```

Bu örnekte **isim** değişkeni **ogrenci** sınıfının bir değişkenidir. Yani bir nesne (obje) oluşturduğunuzda bu nesne üzerinden ilgili değişkene ulaşabilir ve değerini değiştirebilirsiniz fakat yaptığınız değişiklikten tüm nesneler etkilenir.

```python
class ogrenci:
    yas = 10

o1 = ogrenci()
o2 = ogrenci()

ogrenci.yas = 20

print(ogrenci.yas)    # 20
print(o1.yas)         # 20
print(o2.yas)         # 20
```

Örnekte gördüğünüz gibi `o1` ve `o2` olmak üzere iki adet nesne oluşturduk ve sadece sınıf `yas` değişkene ulaşarak değerini değiştirmemize rağmen her iki nesnede de bu değer değişti. **Çünkü yas değişkeni bu nesnelerin kendi değişkeni değil, sınıfın kendi değişkenidir ve nesneler ilgili değişkenlere değer atamadığı sürece tüm değişikliklerden etkilenir.**

{% hint style="warning" %}
Bu şekilde sınıfın kendi değişkenlerini kullanarak objeleri etkili şekilde kullanmayız. Çünkü elimizdeki her objenin *(örneğimizde yer alan öğrencilerin)* kendine has değişken değerleri olmalıdır ve diğer nesnelerden etkilenmemelidir.
{% endhint %}

**init(self)** fonksiyonu Python programlama dilinde bir nesne oluşturulduğunda çalışan özel bir elemandır. Nesne oluşturur oluşturmaz çalışır ve **self** ile içinde oluşturduğumuz değişkenleri nesneye atar. Böylece her nesnenin kendine has değişken değerleri olmuş olur. Bu kısmı örneklerle adım adım anlatalım.

```python
class ogrenci(): 
    yas = 0 
    print("Merhaba")
    
# Merhaba
```

Bu kodu çalıştırır çalıştırmaz ekranda *"Merhaba"* yazısını görürsünüz. Çünkü sınıflar kodlanır kodlanmaz kendi değişkenlerini ve fonksiyonlarını tanımlar. Burada da `ogrenci` sınıfına ait olan `print` komutu çalıştı.

```python
class ogrenci():

    def __init__(self):
        print("Merhaba")
```

Bu kodu çalıştırdığınızda ise ekranda hiçbir çıktı göremezsiniz. Çünkü biraz yukarıda **init(self)** fonksiyonunun sınıf örneklenir örneklenmez, yani sınıftan bir nesne(obje) oluşturduğumuzda çalıştığını öğrendik. Öyleyse kodumuzu şu şekilde düzenlersek ekranda çıktı görebiliriz.

```python
class ogrenci():

    def __init__(self):
        print("Merhaba")

o1 = ogrenci()

# Merhaba
```

Gördüğünüz gibi `o1` isimli nesne oluşturduğumuza ilklendirme fonksiyonumuz çalıştı ve ekrana *"Merhaba"* yazdı. Öyleyse sınıf değişkenlerimize ek olarak nesnelerimize ait olacak değişkenlerimizi de tanımlayalım ve böylece her nesneye özel değişken değeri atayabilelim. Sınıf değişkenleri ise tüm sınıf genelinde değişmeyecek sabit değerler için kullanılabilir. Örneğin pi sayısı gibi.

```python
class ogrenci():

    def __init__(self):
        self.isim = "YOK"
        self.yas = 0

o1 = ogrenci()
o2 = ogrenci()

print(o1.isim + " - " + str(o1.yas))    # YOK - 0
print(o2.isim + " - " + str(o2.yas))    # YOK - 0
```

Burada gördüğünüz gibi nesnemiz oluşturulduğunda `__init__(self)` fonksiyonu objeler oluşturulduğu anda çalıştı ve nesnelerimize ilk değerlerini atadı. **self** değişkeni ise **nesnelerimizi temsil ederek** *(o1 ve o2)* ilgili nesne üzerinde işlem yapılmasını sağladı.

```python
class ogrenci():

    def __init__(self):
        self.isim = None
        self.yas = None

o1 = ogrenci()
o2 = ogrenci()

o1.isim = "Yunus"
o2.isim = "İsmet"

o1.yas = 10
o2.yas = 15

print(o1.isim + " - " + str(o1.yas))    # Yunus - 10
print(o2.isim + " - " + str(o2.yas))    # İsmet - 15
```

Yine bu örnekte olduğu gibi her nesne **self** ile kendi değişkenlerine ulaşarak değer atamalarını gerçekleştirdi.

{% hint style="info" %}
**self** terimi nesneyi temsil eder `(o1.isim)` , `(o2.isim)` gibi doğru nesne üzerinde çalışılmasını sağlar. Siz bu terimi herhangi bir isimle değiştirerek *(örneğin self yerine elma kullanarak)* kullanabilirsiniz ama programlama da **self** kelimesi kalıplaşmıştır.
{% endhint %}

Bu başlığa son bir örnek daha verelim ve sınıf değişkenleri ile nesne değişkenleri arasındaki farkı anlayalım.

```python
class ogrenci():

    yas = 10

    def __init__(self):
        self.yas = 20

o1 = ogrenci()

print(ogrenci.yas)    # 10
print(o1.yas)         # 20
```

Gördüğünüz gibi obje oluşturulduğunda kendi yas değişkenini tanımladı ve sınıf değişkeninden bağımsız olarak kullandı.

```python
class ogrenci():

    def selamVer():
        print("Merhaba")

    def selamVer(self):
        print("Merhaba !!")


o1 = ogrenci()

o1.selamVer()    # Merhaba !!
```

Aynı şekilde `selamVer()` fonksiyonunu nesne üzerinden çalıştırdığımızda kendini temsil eden **self** teriminin olduğu fonksiyonu görerek ilkini değil ikinci fonksiyonu çalıştırdı.

{% hint style="warning" %}
Eğer bir nesne değişkeniyle çalışıyorsanız değişkenin başına **self** terimini getirmeyi unutmayınız.
{% endhint %}

## 6. Ön Tanımlı Değerlerle Obje Oluşturmak

Bir nesneyi isterseniz öntanımlı değerlerle oluşturabilirsiniz. Böylece daha sonrasında tek tek nesne değerleri atamak zorunda kalmazsınız.

```python
class ogrenci:

  def __init__(armut, isim, yas):
    armut.isim = isim
    armut.yas = yas

  def selamVer(armut):
    print("Merhaba, ben " + armut.isim)

o1 = ogrenci("İsmet", 24)
o1.selamVer()
```

{% hint style="info" %}
**self** terimi yerine istediğiniz bir kelime ( **armut** gibi) kullanabilirsiniz demiştik. Fakat siz **self** kullanmakta ısrarcı olun çünkü Python programlama dilinde **self** terimi kalıplaşmıştır.
{% endhint %}

## 7. Nesne ve Obje Değişkeni Silme

Sınıfımızı örneklendirerek istediğimiz kadar nesne oluşturabileceğimizi şimdiye kadar gördük. Peki oluşturduğumuz nesneleri nasıl silebiliriz? Elimizdeki nesneleri **del** terimi ile rahatlıkla silebiliriz.

```python
class ogrenci():
    yas = 10

o1 = ogrenci()

del o1

print(o1.yas)    # !!! HATA !!!
```

Bu örnekte hata alırız çünkü nesnemizi artık mevcut olmadığı için kullanamayız. Aynı şekilde yine **del** terimiyle nesnelerimize ait değişkenleri de silebiliriz.

```python
class ogrenci():

    def __init__(self):
        self.yas = 20

o1 = ogrenci()
o2 = ogrenci()

del o2.yas

print(o1.yas)    # 20
print(o2.yas)    # !!! HATA !!!
```

Burada ise `o2` objesinin `yas` değişkenini sildiğimiz için artık ulaşamıyoruz.

Soru Cevabı Üçüncü başlığımız olan Nesne (Obje) Oluşturma'nın sonundaki sorumuzun cevabına gelmeden önce sorunumuzu bir hatırlayalım: Oluşturduğumuz `sınıf değişkenine` nesneler üzerinden bir değer atamadan direkt `sınıf değişkeni` üzerinden değer atama yaptığımızda tüm `nesnelerdeki değerler` değişiyor ama önce nesne üzerinden sınıf değişkenine değer atadığımızda sınıf değişkeni üzerinden değer atasak bile değer nesnelerde değişmiyor. Sebebi Nedir?

```python
class ogrenci:
    yas = 10

o1 = ogrenci()
o2 = ogrenci()


print(o1.yas)        # 10
print(o2.yas)        # 10
```

Yukarıdaki örnekte objeler `yas` sınıf değişkeninin değerini öntanımlı değerinden alır.

```python
class ogrenci:
    yas = 10

o1 = ogrenci()
o2 = ogrenci()

ogrenci.yas = 20

print(o1.yas)        # 20
print(o2.yas)        # 20
print(ogrenci.yas)   # 20
```

Ama yukarıdaki gibi nesnenin `yas` değişkenine değer atamadan önce sınıf değişkeni üzerinden değer atarsak bu değişiklik tüm nesneleri etkiler.

```python
class ogrenci:
    yas = 10

o1 = ogrenci()
o2 = ogrenci()

o1.yas = 30
ogrenci.yas = 20

print(o1.yas)        # 30
print(o2.yas)        # 20
print(ogrenci.yas)   # 20
```

Fakat yukarıdaki örnekte olduğu gibi önce nesnenin yas değişkenini değiştirirsek artık o nesne için ilgili değer sınıd değişkeni üzerinden değiştirilemez.

Bunun sebebi yas değişkeninin nesnelerin değil sınıfın bir değişkeni olmasıdır. Bu nedenle bu değişken üzerinde yaptığımız bir değişiklik tüm nesneleri etkiler. Fakat siz bir nesne üzerinden bu değere ulaşıp kullandığınızda ilgili değişken ayriyeten objeye has bir değişken olarakta saklanır.

Bu sebeplerden dolayı pi sayısı, firma adı, okul adı gibi değişmeyecek veya değişince herkeste değişmesini istediğiniz değerleri **sınıf değişkeni** olarak tutabilirsiniz. Fakat her nesne için değişecek değerleri **init(self)** fonksiyonu ile oluşturmanızda fayda vardır. Aksi halde bu başlıktaki sorun programınızın düzensiz çalışmasına sebep olabilir.


# # Python Kalıtım

Python kalıtım (inheritance) konusunu işliyoruz.

Python sınıflar konusunu uzunca anlatmamızın ardından şimdi de kalıtım dersine geçtik. Python programlama dersinde kalıtım kullanarak bir üst sınıfın tüm değişken ve methodlarını kendi sınıfınız içinde kullanabiliriz. Kalıtımda;

* **Ebeveyn sınıf;** değişkenlerini ve fonksiyonlarını kalıtım ile kullandırır.
* **Çocuk sınıf;** ebeveyn sınıftan kalıtım ile değişken ve methodaları alarak kullanabilir.

## 1. Ebeveyn Sınıfın Oluşturulması

Bu konuyu bir önceki dersimizde detaylıca işledik. Örnek olması amacıyla şimdi de basit bir sınıf oluşturalım.

```python
class Birey:
    def __init__(self,ad,soyad):
        self.ad= ad
        self.soyad= soyad
        
    def bilgiVer(self):
        print("İsim: " + self.ad + " " + self.soyad)
        
x = Birey("Yunus", "ÖZ")

x.bilgiVer()    # Yunus ÖZ


```

Örnekte gördüğünüz gibi basit bir sınıf oluşturduk ve ürettiğimiz nesne ile nesne özelliklerini kullanabildik. Şimdi kalıtım ile çocuk sınıf üretelim.

## 2. Çocuk Sınıfın Oluşturulması

Python kalıtım ile ebeveyn sınıftan çocuk bir sınıf oluşturarak ebeveyn sınıfın tüm değişkenlerini ve methodlarını alabiliriz. Böylece aynı özellikleri tekrar tekrar oluşturmamıza gerek kalmadan kullanabiliriz.&#x20;

Kalıtım ile ebeveyn sınıftan çocuk sınıf üretebilmek için oluşturacağımız çocuk sınıfa ebeveyn sınıfı parametre olarak göndermemiz gerekiyor.

```python
class Ogrenci(Birey):
    pass
```

İşte bu örnekte gördüğünüz gibi kalıtım ile yeni oluşturduğumuz `Ogrenci` sınıfına `Birey` sınıfını ebeveyn olarak atadık ve ebeveyn sınıfın tüm değişken ve methodlarını yeni sınıfımıza dahil ettik.

```python
class Ogrenci(Birey):
    pass
    
y = Ogrenci("Deniz","SANCAK")

y.bilgiVer()    # Deniz SANCAK
```

`Ogrenci` sınıfında hiçbir değişken ve method oluşturmamamıza rağmen `Birey` sınıfını kalıttığımız için onun özelliklerini kullanabildik.

## 3. Fonksiyon Override Etmek

Çocuk sınıf içerisinde eğer kendi fonksiyonunuzu kullanırsanız kalıtılan ebeveyn sınıfın fonksiyonu geçersiz hale gelir yani **override (geçersiz kılmak)** edilir.

```python
class Ogrenci(Birey):
    def bilgiVer(self):
        print("Merhaba, ben " + self.ad + " " + self.soyad)
    
y = Ogrenci("Deniz","SANCAK")

y.bilgiVer()    # Merhaba, ben Deniz SANCAK
```

Bu örnekte yeni bir `bilgiVer()` fonksiyonu tanımladığımız için ebeveyn sınıfın `bilgiVer()` fonksiyonunu geçersiz kıldık ve yeni `bilgiVer()` fonksiyonumuzu kullandık.&#x20;

## 4. super() Fonksiyonu Kullanımı

Kalıtım ile aldığımız özellikleri override ettiğimizde artık ebeveyn sınıfın değil, çocuk sınıfın özelliklerini kullandığımızı bir üst başlıkta gördük. Şimdi ise ebeveyn sınıfın özelliklerini geçersiz kılsak bile (override) tekrardan nasıl kalıttığımız ebeveyn sınıfın özelliklerini kullanacağımızı gösterelim.

```python
class Ogrenci(Birey):
    def bilgiVer(self):
        super().bilgiVer()
    
y = Ogrenci("Deniz","SANCAK")

y.bilgiVer()    # İsim: Deniz SANCAK
```

Bu örnekte `bilgiVer()` fonksiyonunu geçersiz kılmamıza rağmen **`super()`** fonksiyonu ile ebeveyn sınıfın `bilgiVer()` fonksiyonunu çağırdık ve kullandık. Aynı şeyi ebeveyn sınıfın ismiyle de yapabilirsiniz fakat **self** terimini eklemeyi unutmayın.

```python
class Ogrenci(Birey):
    def bilgiVer(self):
        Birey.bilgiVer(self)
    
y = Ogrenci("Deniz","SANCAK")

y.bilgiVer()    # İsim: Deniz SANCAK
```

Bu özelliği çocuk sınıfında ilgili fonksiyonu geliştirmek için kullanabilirsiniz. Yani ebeveyn sınıfın fonksiyonunu geçersiz kılmadan ona yeni özellikler ekleyebilirsiniz.

```python
class Ogrenci(Birey):
    def __init__(self,ad,soyad,sinif):
        super().__init__(ad,soyad)
        self.sinif = sinif
        
y = Ogrenci("Deniz","SANCAK",1)

y.bilgiVer()      # İsim: Deniz SANCAK
print(y.sinif)    # 1
```


# Dosya İşlemleri

Python dosya işlemleri ile okuma, yazma, güncelleme ve silme işlemlerini göreceğiz.

Python ile dosya işlemleri önemli bir konudur. Fakat öncesinde dosya nedir sorusunu cevaplayalım.

Unix işletim sistemlerinde **her nesne bir dosyadır**. Yani elinizdeki metin belgeleri, medya dosyaları gibi herşey uzantısı olsun veya olmasın bir dosya demektir. Sizde bu dosyalar üzerinde özgürce çalışabilirsiniz.

Artık dosyalar üzerinde yapabileceğimiz tüm işlemleri sırasıyla görebiliriz.

## 1. Dosya İşlem Kipleri

Dosyalar üzerinde okuma, yazma, güncelleme ve silme işlemi yapmadan önce dosyalarımızı hangi **modlarda (kiplerde)** kullanabileceğimizi görelim.

| MOD | AÇIKLAMA                                                                       |
| --- | ------------------------------------------------------------------------------ |
| r   | Mevcut dosyayı okumak için açar, yoksa hata verir                              |
| w   | Dosya yoksa oluşturur, varsa içeriği silerek sıfır dosya açar                  |
| a   | Dosya yoksa oluşturur, varsa dosyanın sonunda imleçten başlayarak ekleme yapar |
| r+  | Dosyayı hem okuma, hem yazma(w) modunda açar                                   |

## 2. Dosya Okuma & Açma İşlemleri

Bu örneklerde basit bir `txt` uzantılı metin belgesi ile çalışacağız fakat siz herhangi bir dosya ile de aşağıdaki örnekleri gerçekleştirebilirsiniz. Hatta `png` uzantılı resimlerle bile çalışabilirsiniz. Çünkü unutmayınız ki herşey bir dosyadır.

### 2.1 Dosyayı Seçme

Aşağıdaki yöntemle dosyamızı seçiyoruz ve **işlem kipini (r-read)** belirtiyoruz. Ayrıca karakter kodlamasını da fonksiyona dahil edebiliriz.

```python
dosya = open("bilgiler.txt","r",encoding="utf-8")
```

Artık okuyacağımız dosyayı seçmiş bulunuyoruz. Bundan sonra işlemlerimize daha rahat devam edebiliriz.

### 2.2 Tüm Dosyayı Ekrana Yazdırma / `read()`

Dosyayı seçtikten sonra direkt ekrana basmak isteyebiliriz. Bunun için şu şekilde bir kullanımı tercih edebiliriz:

```python
dosya = open("bilgiler.txt","r",encoding="utf-8")
oku = dosya.read()
print(oku)
```

Eğer biz `read()` fonksiyonuna bir sayı değeri verirsek sadece o sayı değeri kadar alanı okuyacaktır. Hemen görelim.

```python
dosya = open("bilgiler.txt","r",encoding="utf-8")
oku = dosya.read(10)  #Sadece ilk 10 karakteri okur
print(oku)
```

{% hint style="info" %}
Artık metin belgemizin tamamını ekranda görebiliriz ama unutmayınız ki bu fonksiyon çalıştığında imleci dosyanın sonuna götürür. Yani tekrar aynı fonksiyonu çağırırsanız bu sefer imleç en sonra olduğu için ekrana basılan bir içerik göremezsiniz.
{% endhint %}

### 2.3 Her Seferinde Sıradaki Satırı Ekrana Yazdırma / `readline()`

Şimdi sırada satır satır okuma işlemi yer alıyor. `readline()` fonksiyonunu her çağırmamızda sadece bir satır okursunuz. Yani ilk çağırdığınızda dosyanın ilk satırını, ikinci çağırdığınızda dosyanın ikinci satırını okursunuz. Bunu döngüye sokarak tüm dosyayı satır satır okuyabilirsiniz.

```python
dosya = open("bilgiler.txt","r",encoding="utf-8")

print(dosya.readline()) #1.satırı yazdır
print(dosya.readline()) #2.satırı yazdır
print(dosya.readline()) #3.satırı yazdır
```

Buradaki tek sorun döngüye soktuğumuzda döngünün kaçıncı satırda biteceğini bilemememiz. Bunu öğrenmenin farklı farklı yöntemleri var ama bize zaman kaybettirmekten başka birşey sağlamaz. Bu yüzden aşağıdaki methodu kullanmanız daha mantıklı olacaktır.

### 2.4 Dosyayı Satır Satır Döngüyle Ekrana Yazdırma / `with`

Bir dosyayı satır satır yazdırabilmemiz için `readline()` dışında kullanabileceğimiz 2 yöntemimiz var. İki yöntemde aynı kapıya çıkıyor. Bu nedenle aşağıdaki kullanım şekillerinden hoşunuza gideni direkt kullanabilirsiniz.

> Yöntem-1

```python
dosya = open("a.txt","r")
for satir in dosya:
   print(satir)
```

> Yöntem-2

```python
with open("a.txt","r") as dosya:
   for satir in dosya:
        print(satir)
```

### 2.5 Dosyanın Her Satırını Diziye Eklemek / `readlines()`

`readline()` fonksiyonu her çağırdığımızda dosyayı satır satır okumamızı sağlıyordu. `readlines()` ise çağırdığımızda dosyanın tüm satırlarını bir diziye atar. Böylece her satır dizinin bir elemanı olur. Kullanım şeklini ve sonucunu aşağıda görebilirsiniz.

{% tabs %}
{% tab title="Komut" %}

```python
dosya = open("a.txt","r")
dizi = dosya.readlines()
print(dizi)
```

{% endtab %}

{% tab title="Çıktı" %}

```python
['a\n', 'b\n', 'c\n', 'd\n', 'e']
```

{% endtab %}
{% endtabs %}

{% hint style="info" %}
&#x20;Dosya işlemlerinde okuduğunuz satırların sonunda **`/n`** kısmını görebilirsiniz. Bir alt satıra inmeyi işaret eden bu kodu **`rstrip("/n")`** fonksiyonuyla temizleyebilirsiniz.
{% endhint %}

## 3- Dosyaya Yazma İşlemleri

Dosyalarımızı artık rahatça okuyabiliyoruz. Peki bu dosyalara istediğimiz verileri nasıl ekleyebiliriz? Bu sorunun cevabı da birazdan göreceğiniz gibi oldukça basit. Sadece dikkat etmeniz gereken tek nokta var ve buda dosyayı hangi kipte yazma moduna alacağınızdan başka birşey değil. &#x20;

Şimdiki konumuz dosyaya veri yazmak olduğu için biz sadece `w` ve `a` modlarını kullanacağız.

### 3.1 w Moduyla Dosyaya Veri Yazmak

&#x20;`w` kipiyle açtığımız dosyalar yoksa oluşturulur. Varsa dosyanın içeriği önce silinerek temizlenir ve ardından yazmak istediğimiz veriler eklenir. Kısaca eski veriler yok olur. Bu nedenle `w` modunu dikkatli kullanınız.

```python
dosya = open("bilgiler.txt","w",encoding="utf-8")

dosya.write("Kerteriz ile Python Dosya İşlemleri\n")
dosya.write("Burası 2. satır oluyor artık")
dosya.write("3.satıra inmeden 2.satırın sonundan itibaren yazıyor")
```

Yukarıdaki işlemlerden sonra dosyayı açarsanız karşınızda bu yazdıklarımızı göreceksiniz. Dosyayı kapatana kadar yazmaya da devam edebilirsiniz (dosya kapatma işlemini en sonra göreceğiz)

### 3.2 a Moduyla Dosyaya Veri Yazmak

`a` modu da yine aynı şekilde dosyaya veri yazmamızı sağlar ama tek farkı mevcut dosyanın içeriğini silmez. Bunun yerine dosyanın sonundan yeni verileri eklemeye başlar.

```python
dosya = open("bilgiler.txt","a",encoding="utf-8")

dosya.write("Kerteriz ile Python Dosya İşlemleri\n")
dosya.write("Burası 2. satır oluyor artık")
dosya.write("3.satıra inmeden 2.satırın sonundan itibaren yazıyor")
```

Eğer bilgiler.txt nin içinde daha önceden yazılı başka metinler varsa silinmediğini göreceksiniz.

{% hint style="info" %}
Dosyalara yazma işlemi yaparken satır eklemek isterseniz **`\n`** kullanmalısınız. Aksi halde tüm yazdıklarınız tek satırda yan yana dizilir.
{% endhint %}

## 4. Dosya Silmek

Dosyalarınızı silmek istediğinizde **`os`** modülünü programınıza dahil etmeniz gerekiyor. Ardından **`remove()`** fonksiyonu sile dosyanızı silebilirsiniz.

```python
import os
os.remove("dosya.txt")
```

Eğer silmek istediğiniz nesne bir klasörse bu sefer **`rmdir()`** fonksiyonunu kullanmalısınız.

```python
import os
os.rmdir("resimler")
```

## 5. Dosyaları Kapatmak

Dosyalar üzerindeki işiniz bittiğinde kapatmanız gerekiyor. Bunun için `close()` adından da anlaşılacağı üzere yardımımıza koşuyor.

```python
dosya = open("bilgiler.txt","a",encoding="utf-8")
dosya.close()
```

Çoğu kez dosyalarımızı kapatmayı unuttuğumuz için Pythonun otomatik dosya kapatma özelliğini kullanmak daha iyidir. Bunun için dosyalarınızı açarken şu şekilde açarsanız manuel olarak dosya kapatmaya ihtiyacınız kalmayacaktır.

```python
with open("bilgiler.txt","a",encoding="utf-8") as dosya:
    #kullanıcak fonksiyonlar
    #......
    #......
```

## 6. Özel Dosya Fonksiyonları

### 6.1 Dosyanın Var Olup Olmadığını Kontrol Etmek

Üzerinde çalışmak istediğiniz bir dosyanın öncelikle var olup olmadığını kontrol etmek hataların önüne geçebilir. Bu kontrolü **`os`** modülüyle şu şekilde yapabilirsiniz.

```python
import os

if os.path.exists("bilgiler.txt"):
  print("Dosya var")
else:
  print("Dosya mevcut değil!")
```

### 6.2 İmlecin Nerede Olduğunu Öğrenme

Biraz sonra göreceğimiz imleci dosyada istediğimiz yere koyma işlemlerine gelmeden önce imlecin nerede olduğunu öğrenmekle başlayalım konuya. Aşağıdaki fonksiyon sayesinde imlecin dosyanın kaçıncı **byte** nda olduğunu öğrenebiliriz.

```python
with open("bilgiler.txt","r",encoding = "utf-8") as dosya:
    print(dosya.tell())
```

Örneğin dosyada bir `read()` işlemi yaptıysanız imleç dosyanın sonuna gider ve yukarıdaki fonksiyon size dosyanın **byte** miktarını gösterir. Hiçbir işlem yapmadıysanız da dosyanın başında olduğunuzu söyler, yani 0 gösterir.

### 6.3 Dosyanın Belirli Bir Byte'ına İmleci Koymak

Eğer imlecimizi dosyada istediğimiz bir byte'a koymak istiyorsak bunu şu şekilde yapabiliriz.

```python
with open("bilgiler.txt","r",encoding = "utf-8") as dosya:
    print(dosya.seek(20))  #20. byte'a imleci koyar
```

### 6.4 Dosyanın Sonuna Veri Eklemek

Bu işlem için dosyayı `a` kipinde açıp write ile verilerinizi eklemeniz yeterli olacaktır

### 6.5 Dosyanın Başına Veri Eklemek

Bu işlemi yapabilmenin en kolay yolu dosyanın tamamını okuyup başına istediğimiz veriyi ekleyerek yeni bir string olarak kaydetmek, ardından imleci başa getirerek yeni veriyi yazmak olacaktır. Hemen görelim:

```python
with open("bilgiler.txt","r+",encoding = "utf-8") as dosya:
    icerik = dosya.read()
        yeniicerik = "Bu metini ilk satıra ekliyorum\n" + icerik
        dosya.seek(0)
        dosya.write(yeniicerik)
```

&#x20;İşte bu kadar basit. Sadece farklı olarak dosyayı `r+` modunda açtık çünkü dosyayı hem okuyor, hem yazıyoruz.


# Veritabanı İşlemleri

Python Mysql, Mssql, Sqlite ve Mongodb veritabanı işlemlerini bu başlık altında detaylıca işleyeceğiz.


# # Python SQLite Veritabanı

Python Sqlite veritabanı işlemlerini öğreniyoruz.

SQLite, hafif ve disk tabanlı bir veritabanı çözümüdür. Herhangi bir ayrı sunucu işlemine gerek kalmadan ve basit standart sql söz dizimi ile cihazların yerel hafızalarında bile kullanılabilir. Birçok dil ile kullanımı olduğu gibi Python ile de rahatlıkla entegre dilebilir.

## 1. SQLite Avantajları

* Bir modül olarak projenize rahatlıkla dahil edebilirsiniz
* Ayrı bir yazılım veya sunucu kurmanıza gerek yoktur.
* Veritabanını diskinizde saklayabilirsiniz ve kolaylıkla transfer edebilirsiniz.
* Söz dizimi oldukça basittir, rahat öğrenilebilir.
* Açık kaynak kodludur, istediğiniz düzenlemeleri yapabilirsiniz.

SQLite her ne kadar basit bir veritabanı gibi gözüksede oldukça güçlü bir veritabanıdır ve kullanımı yaygındır.

## 2. Veritabanı İşlemleri

Python ile SQLite veritabanı üzerinde yapacağımız işlemleri bu başlık altında sırasıyla işleyeceğiz. Fakat öncesinde **`sqlite3`** modülünü projenize dahil etmelisiniz.

```python
import sqlite3
```

Ardından işlemlerimize geçebiliriz.

### 2.1 Veritabanı Oluşturma

İlk olarak yeni bir veritabanı oluşturmak veya mevcut  bir veritabanına bağlanmak için **`connect()`** fonksiyonunu kullanmalıyız. Bağlanacağımız veritabanı mevcut değilse otomatik olarak oluşturulacaktır.

```python
db = sqlite3.connect('veritabanı_adı.db')
```

{% hint style="info" %}
SQLite veritabanı uzantısı herhangi bir terim olabilir. Genel olarak **`db`**, **`db3`**, **`sqlite`** ve **`sqlite3`** kullanılır ama siz başka bir isimde seçebilirsiniz. *(Örneğin veritabani.elma)*
{% endhint %}

Eğer isterseniz veritabanını tam adres göstererek de oluşturabilirsiniz.

```python
db = sqlite3.connect('/home/kerteriz/test.sqlite') #GNU/Linux
db = sqlite3.connect('c:/users/kerteriz/desktop/test.sqlite') #Windows
```

Aynı şekilde RAM veya sabit disk üzerinde geçici bir veritabanı da oluşturabilirsiniz.&#x20;

```python
db = sqlite3.connect(':memory:')    # RAM üzerinde geçici db
db = sqlite3.connect('')            # HDD üzerinde geçici db
```

{% hint style="info" %}
Daha çok test ortamları için kullanılan geçici veritabanları program sonlandırıldığında veya veritabanı bağlantısı kapatıldığında silinecektir.
{% endhint %}

### 2.2 İmleç Oluşturma

Yeni oluşturduğumuz veya mevcut olan bir veritabanına bağlandıktan sonra üzerinde işlem yapabilmek için **`cursor()`** fonksiyonu ile imleç oluşturmamız gerekiyor.

```python
imlec = db.cursor()
```

### 2.3 Yeni Tablo Oluşturma

SQL komutlarını oluşturabilmek için imlecimizle beraber **`execute()`** fonksiyonunu kullanmalıyız. Böylelikle tüm SQL komutlarını veritabanımız üzerinde çalıştırabiliriz.

```python
imlec.execute("CREATE TABLE ogrenciler(isim, yas)")
```

Artık veritabanımızda **ogrenciler** isimli ve iki sütunlu (isim,yas) bir tablo oluşturmuş olduk. Daha uzun komutlarınızı daha rahat okuyabilmek için `"""` işareti ile birden fazla satırda kullanabilirsiniz.

```python
imlec.execute(""""CREATE TABLE ogrenciler 
(isim, yas, sinif, veli, telefon, email)""")
```

Ayrıca daha rahat bir kullanım için sql komutlarınızı bir değişkene atayarak `execute()` fonksiyonuna da gönderebilirsiniz.

```python
komut = "CREATE TABLE ogrenciler(isim, yas)"

imlec.execute(komut)
```

{% hint style="warning" %}
Yukarıdaki yöntemlerle tablo oluşturduğunuzda tekrar aynı komutu çalıştırırsanız zaten bir kere oluşturulduğu için ***"sqlite3.OperationalError: table ogrenciler already exists"*** hatası verecektir.&#x20;
{% endhint %}

Uyarıda ki hatayı engellemek için tablo oluşturma komutunu **`IF NOT EXISTS`** ile güncelleyiniz. Böylece tablo zaten mevcutsa tekrardan oluşturulmaya çalışılmayacaktır.

```python
komut = "CREATE TABLE IF NOT EXISTS ogrenciler(isim, yas)"

imlec.execute(komut)
```

### 2.4 \~INSERT\~ ile Yeni Satır Ekleme

Tablomuza yeni veriler girebilmek için sql **`INSERT`** komutunu kullanmalıyız.

```python
komut = """INSERT INTO ogrenciler VALUES ('Yunus', 25)"""

imlec.execute(komut)
```

Aynı mantıkla komutumuzu yazdık ve imleç ile veritabanına işlettik. Fakat veritabanımızı kontrol ettiğinizde yeni verilerin eklenmemiş olduğunu göreceksiniz. Eğer yapılan değişikliklerin veritabanına uygulanmasını istiyorsanız **`commit()`** fonksiyonunu çalıştırmanız gerekiyor.

```python
db.commit()
```

Artık yeni verileri tablonuzda görebilirsiniz.

### 2.5 \~SELECT\~ ile Tablodaki Verileri Seçmek

Tablomuza örnek veriler ekledikten sonra bu verileri seçmek için **`SELECT`** komutunu kullanırız.

| isim  | yas |
| ----- | --- |
| Yunus | 24  |
| Ahmet | 30  |
| Deniz | 15  |

Örnek tablomuzdaki tüm verileri çekmek için öncelikle sql komutumuzu çalıştıralım ve ardından **`fetchall()`** fonksiyonu ile tüm verileri değişkenimize atalım. Ardından tüm verilerimiz demet halinde dönecektir.

```python
komut = """SELECT * FROM ogrenciler"""

imlec.execute(komut)

veriler = imlec.fetchall()

print(veriler)    # [('Yunus', 25), ('Ahmet', 30), ('Deniz', 15)]
```

Tüm satırları çekmek istediğimizde **`for`** terimini de kullanabiliriz.&#x20;

```python
komut = """SELECT * FROM ogrenciler"""

imlec.execute(komut)

for veri in imlec:
    print(veri)
    
# ('Yunus', 25)
# ('Ahmet', 30)
# ('Deniz', 15)
```

Eğer tek tek satır çekmek istiyorsanız bu sefer **`fetchone()`** fonksiyonunu kullanmalısınız. `fetchone()` fonksiyonu her çalıştığında sıradaki satırı çeker.

```python
komut = """SELECT * FROM ogrenciler"""

imlec.execute(komut)

print(imlec.fetchone())    # ('Yunus', 25)
print(imlec.fetchone())    # ('Ahmet', 30)
print(imlec.fetchone())    # ('Deniz', 15)
```

Çektiğiniz tek bir satırın sütunlarına ulaşmak için demet elemanlarını kullanabiliriz.

```python
komut = """SELECT * FROM ogrenciler WHERE yas = {}""".format(15)

imlec.execute(komut)

veri = imlec.fetchone()

print("İsim: " + str(veri[0]))    # İsim: Deniz
print("Yaş: " + str(veri[1]))     # Yaş: 15
```

Tümünü veya tekini çekmek yerine belirlediğiniz adette satır çekmek için **`fetchmany()`** fonksiyonunu kullanabilirsiniz.

```python
komut = """SELECT * FROM ogrenciler"""

imlec.execute(komut)

veriler = imlec.fetchmany(2)

print(veriler)    # [('Yunus', 25), ('Ahmet', 30)]
```

Adet sayısınca çekeceğiniz veriler üzerinde **`fetchone()`** fonksiyonu ile gezerken **`for`** döngüsünü de kullanabiliriz.

```python
komut = """SELECT * FROM ogrenciler"""

imlec.execute(komut)

for veri in range(2):
    
    print(imlec.fetchone())
    
# ('Yunus', 25)
# ('Ahmet', 30)
```

### 2.6 \~UPDATE\~ ile Veri Güncelleme

Elimizdeki tabloda yer alan veriler üzerinde bir güncelleme yapmak istediğimizde **`UPDATE`** sql komutunu kullanırız. Örnek verirsek elimizde aşağıdaki gibi bir tablo olduğunu farzedelim.

| isim  | yas |
| ----- | --- |
| Yunus | 25  |
| Özlem | 15  |
| Ahmet | 30  |

Örnek tablomuz üzerindeki *Ahmet* isimli kullanıcının yaşını *50* olarak güncelleyelim.

```python
komut = "UPDATE ogrenciler SET yas = ? WHERE isim = ?"

imlec.execute(komut,(50,'Ahmet'))
db.commit()
```

Verileri **?** ile işaretleyip verileri **demet** halinde **`execute()`** fonksiyonuna vermemizin ardından hemen sonucu kontrol edelim.

```python
komut = """SELECT * FROM ogrenciler"""

imlec.execute(komut)

veri = imlec.fetchall()

print(veri)    # [('Yunus', 25), ('Özlem', 15), ('Ahmet', 50)]
```

### 2.7 \~DELETE\~ ile Veri Silme

Tablomuz üzerindeki bir veriyi silmek için **`DELETE`** sql komutunu kullanmalıyız. Örnek olarak aynı tablo üzerinde yer alan *Yunus* kullanıcısını silelim.

```python
komut = "DELETE FROM ogrenciler WHERE isim = ?"

imlec.execute(komut,('Yunus',))
db.commit()
```

Tek elemanlı bir demet kullandığımız için elemandan sonra virgül koyuyoruz ve *Yunus* isimli satırı silmek istediğimizi söylüyoruz. Ardından sonucumuz şu şekilde oluyor.

```python
komut = """SELECT * FROM ogrenciler"""

imlec.execute(komut)

veri = imlec.fetchall()

print(veri)    # [('Özlem', 15), ('Ahmet', 50)]
```

### 2.8 Veritabanı Bağlantısını Kapatmak

Veritabanı üzerindeki işlerinizi tamamladığınızda veritabanı bağlantısını sonlandırmak için **`close()`** fonksiyonunu kullanmalısınız.

```python
db.close()
```

## 3. SQLite Browser Kullanımı

SQLite Browser, elinizdeki veritabanı üzerindeki çalışmalarınızı bir arayüz üzerinden yapmanızı sağlar. Basit ve kullanışlı arayüzü ile tüm veritabanı işlemlerinizi rahatlıkla yapabilirsiniz.

![Sqlite Browser programının arayüzü](/files/-Lw-sC7V2C_KMgV6kFK6)

> SQLite Browser programını indirmek için [tıklayınız.](https://sqlitebrowser.org/dl/)

## 4. Özet

Tüm işlemleri kısaca özetlersek sırasıyla şu işlemleri yapmalısınız.

1. `sqlite3` modülünü projenize dahil edin
2. Mevcut veya yeni veritabanınızı `connect()` fonksiyonu ile bağlayın
3. `cursor()` fonksiyonu ile imleç oluşturun
4. Sql komutlarınızı `execute()` fonksiyonu ile işletin.
5. Veritabanınızda değişiklik olacaksa `commit()` edin.
6. Veritabanı bağlantınızı `close()` ile sonlandırın.


# # Python MySQL Veritabanı

Python MySQL veritabanı işlemlerini öğreniyoruz.

MySQL, programlamada en yaygın kullanılan ve en popüler ilişkisel veritabanı yazılımıdır. Sektörün önde gelen firmalarının neredeyse tamamına yakını MySQL ile beraber çalışır vaziyetteler. Hem bu sebeple hem de sunduğu güçlü çözümlerle bizde bu dersimizde MYSQL ve Python ilişkisini anlatacağız.

![MySQL kullanan siteler](/files/-Lw4x5Ql89-WhOVPtqzh)

## 1. MySQL Avantajları

* Açık kaynak kodludur ve ücretsizdir. (Ücretli versiyonu da mevcuttur)
* Farklı karakter setlerini (iso8859-9, utf-8, latin-5 …) destekler
* Çok esnek ve güçlü bir kullanıcı erişim kısıtlama/yetkilendirme sistemine sahiptir
* Güvenlik açısından kendini kanıtlamıştır
* Döküman ve eğitim konusunda geniş kaynağa sahiptir
* Birçok programlama dili ve platformla birlikte kullanılabilir.

## 2. Veritabanı İşlemleri

MySQL veritabanı yazılımını Python ile birlikte nasıl kullanacağımızı aşama aşama görelim.

### 2.1 Kütüphanenin Kurulması ve Projeye Dahil Etme

MySQL ile veritabanı işlemlerimizi rahatça yapabilmemiz için **PyMySql** kütüphanemizi projemize dahil etmemiz gerekiyor.&#x20;

```
import pymysql.cursors
```

Eğer kütüphane bilgisayarınızda kurulu değilse **pip** kullanarak bilgisayarınıza yükleyebilirsiniz.

```
pip install PyMySQL
```

### 2.2 MySQL Veritabanı Bağlantısı <a href="#id-2-mysql-veritaban-ba-lant-s" id="id-2-mysql-veritaban-ba-lant-s"></a>

Artık veritabanımıza bağlantımızı yapacak bilgileri oluşturmanın zamanı geldi. Bunun için aşağıdaki kod blokunu ekleyerek kullanıcı adı, şifre ve veritabanı adını kendinize göre düzenlemelisiniz:

```python
# Veritabanı bağlantı bilgileri
db = pymysql.connect(host='localhost',
                             user='dbkullaniciadi',
                             password='dbparolasi',
                             db='dbadı',
                             charset='utf8mb4',
                             cursorclass=pymysql.cursors.DictCursor)

```

### 2.3 İmleç Oluşturma

Veritabanına bağlandıktan sonra üzerinde işlem yapabilmek için **`cursor()`** fonksiyonu ile imleç oluşturmamız gerekiyor.

```python
imlec = db.cursor()
```

Eğer bilgiler doğruysa python dosyanızı çalıştırdığınızda bir hata almamanız gerekiyor. Boş bir çıktı görüyorsanız ilk iki aşamayı başarıyla geçtiniz demektir:

![Başarılı İşlem](/files/-Lw58P8cBquvkZ05_lOO)

### 2.4 \~SELECT\~ ile Tablodaki Verileri Seçmek <a href="#id-3-select-i-lemi" id="id-3-select-i-lemi"></a>

En çok kullanılan komut olan `SELECT` ile başlayalım. Bunun için ilk önce veritabanımızda örnek bir tablo oluşturalım. Örnek olarak **kullanicilar** isimli tabloyu oluşturmak ve basit olması için sadece `id`, `ad`, `yas` sütunlarını kullanmak istiyorum. İlk başta örnek olarak 2-3 tane veride ekleyebilirsiniz:

![kullanicilar isimli tablo](/files/-Lw58k6ydPLK9wogn66I)

Tablomuz ve örnek verilerimiz hazırsa sorgu kodumuzu hemen gönderelim:

```python
imlec.execute('SELECT * FROM kullanicilar')
```

Bu isteğin ardından dönen sonuçları (dizi olarak döner) bir değişkene aktarmamız gerekiyor. Bunun içinde aşağıdaki gibi bir eşitleme yapıyoruz:

```python
kullanicilar = imlec.fetchall()
```

Artık tablomuzdaki kullanıcılarımızı bir değişkene atadık ve sıra ekrana yazdırmaya geldi. Bunun için **foreach** döngümüzü kullanarak dönen diziyi ekrana yazdırıyoruz:

```python
for i in kullanicilar:
    print(i)
```

Ekran çıktımız şu şekilde olacaktır:

![Döngü sonucu](/files/-Lw59AHdq469Ws3CY3mc)

Eğer dönen sonuçları daha detaylı kullanmak istiyorsanız sütun isimlerini kullanarak ekrana yazdırabilirsiniz. Bunun için:

```python
for i in kullanicilar:
    print("Ad: " + i['ad'] + " --- " + "Yaş: " + str(i['yas']) )
```

Ekran çıktımız şu şekilde olacaktır:

![](/files/-Lw59Tgw72fA83gy4f0-)

&#x20;Özet olarak **execute** fonksiyonu ile hangi komutu gönderirseniz dönen sonuçlar komutun çıktısı olacaktır. Sizlerde istediğiniz komutları yukarıdaki örnekteki gibi gönderebilirsiniz.

### 2.5 \~INSERT\~ ile Yeni Veri Ekleme İşlemi <a href="#id-4-insert-i-lemi" id="id-4-insert-i-lemi"></a>

Tablomuza yeni bir kullanıcı eklemek istediğimizde kullanmamız gereken kod `INSERT` komut yapısı aşağıdaki gibidir:

```python
sonuc = imlec.execute('INSERT INTO kullanicilar VALUES(%s,%s,%s)',(None,'Özlem',25))
db.commit()

print(str(sonuc) + " kullanıcı eklendi")
```

Sonucumuza bakarsak:

![](/files/-Lw59kE4gjph1eaqPcSD)

![](/files/-Lw59oFeQCjCGhSzLLm2)

Yukarıdaki kodda **`%s`** ile göndereceğimiz değerleri belli ediyoruz. Tablomuzda id,ad ve yas sütunları olduğu için **`%s`** ile belirlediğim değişkenleri bir sonraki parametrede yazarak gönderiyoruz. Yani **insert** işleminin kabaca syntax yapısı şu şekildedir:

> imlec.execute = (**SQL Komutu**,**Değişkenler**)

Bu fonksiyon çalıştığında etkilenen girdi sayısını da **sonuc** değişkenimize aktarıyoruz. Bu **sonuc** değişkeni ile tabloya veri eklenip eklenmediğini kontrol edebilirsiniz. Eğer sonuç 0 ise tabloya eklenememiştir.

En önemli kısmına gelirsek te **`db.commit()`** ile yaptığımız değişiklikleri veritabanına ileterek **insert** işlemini gerçekleştiriyoruz. Eğer `commit()` işlemini yapmazsanız insert işlemleriniz gerçekleşmez!

Unutmadan söyleyelim ki **None** değerini tablodaki **id** sütunumu auto increment ayarladığım için boş gönderiyorum, böylece veri eklediğimde id değeri otomatik olarak 1 artıyor.

### 2.6 \~UPDATE\~ ile Veri Güncelleme İşlemi <a href="#id-5-update-i-lemi" id="id-5-update-i-lemi"></a>

Şimdi geldik tablomuzdaki mevcut bir değeri güncellemeye. Bu işlem için `UPDATE` komutunu kullanacağız. Aşağıdaki örneği hemen incelemeye başlayabilirsiniz

```
sonuc = imlec.execute('UPDATE kullanicilar SET yas = %s WHERE id = %s',(50,5))
db.commit()

print(str(sonuc) + " kullanıcı güncellendi")
```

Bu işlemin sonucunda ekran çıktılarımız şu şekilde olacaktır:

![](/files/-Lw5AsXB-F2Xz9EZSRWW)

![](/files/-Lw5AuOnoacmtae1iMJB)

Gördüğünüz gibi klasik Update komutumuzu gönderdik ve işin kritik noktası olan `commit()` ile işlemlerimizi başarıyla tamamladık. Artık sıradaki işlemimize geçebiliriz.

![](/files/-Lw5B5XXhnpSYldIP1U8)

![](/files/-Lw5B80z5itLJPXr9m6C)

Tablomuzdaki kayıt başarıyla silinmiş.

### 2.7 \~DELETE\~ ile Veri Silme

Tablomuz üzerindeki bir veriyi silmek için **`DELETE`** sql komutunu kullanmalıyız. Örnek olarak aynı tablo üzerinde yer alan *Yunus* kullanıcısını silelim.

```
sonuc = imlec.execute('DELETE FROM ogrenciler WHERE ad= %s',('Yunus'))
db.commit()
```

### 2.8 Veritabanı Bağlantısını Kapatmak

Veritabanı üzerindeki işlerinizi tamamladığınızda veritabanı bağlantısını sonlandırmak için **`close()`** fonksiyonunu kullanmalısınız.

```python
db.close()
```

## 3. Özet

Tüm işlemleri kısaca özetlersek sırasıyla şu işlemleri yapmalısınız.

1. `pymysql.cursors` modülünü projenize dahil edin
2. Veritabanınızı `connect()` fonksiyonu ile bağlayın
3. `cursor()` fonksiyonu ile imleç oluşturun
4. Sql komutlarınızı `execute()` fonksiyonu ile işletin.
5. Veritabanınızda değişiklik olacaksa `commit()` edin.
6. Veritabanı bağlantınızı `close()` ile sonlandırın.


# # Python MSSQL Veritabanı

Python MSSQL veritabanı işlemlerini öğreniyoruz.

Python ile veritabanı işlemleri programlamada önemli bir konuma sahiptir. Bu dersimizde verileri veritabanında saklamak ve yeri geldiğinde kullanmak için Python MSSQL bağlantısını ve SELECT, INSERT, UPDATE, DELETE işlemlerini nasıl yapacağız öğreneceğiz.

Daha önceki dersimizde Python Mysql Veritabanı bağlantısını görmüştük, bu dersimizde de Python MSSQL veritabanı bağlantısı dersi ile Python programlama konusunda önemli bir konuyu daha işlemiş bulunacağız.

## 1. `pypyodbc` Kütüphanesinin Kurulması ve Projeye Dahil Etme <a href="#id-1-pypyodbc-k-t-phanesinin-kurulmas-ve-projeye-dahil-etme" id="id-1-pypyodbc-k-t-phanesinin-kurulmas-ve-projeye-dahil-etme"></a>

MSSQL ile veritabanı işlemlerimizi rahatça yapabilmemiz için `pypyodbc` kütüphanemizi kurmamız gerekiyor. Bunun için aşağıdaki komutu kullanarak pip ile kütüphanemizi indirelim:

```
pip install pypyodbc
```

Artık kütüphanemizi kurduğumuza göre projemize kütüphaneyi dahil edebiliriz. Bunu yapabilmek için sayfamızın en üstüne aşağıdaki kodu ekleyelim:

```
import pypyodbc
```

Kütüphaneyi indirip projemize dahil ettikten sonra artık örneklerimize başlayabiliriz.

## 2. MySQL Veritabanı Bağlantısı <a href="#id-2-mysql-veritaban-ba-lant-s" id="id-2-mysql-veritaban-ba-lant-s"></a>

Artık veritabanımıza bağlantımızı yapacak bilgileri oluşturmanın zamanı geldi. Bunun için öncelikle hangi yöntemle veritabanına bağlanacağımızı seçmeliyiz. Nu iki yöntemi de sırasıyla görelim:

### 2.1 Windows Authentication İle Bağlantı <a href="#id-2-1-windows-authentication-i-le-ba-lant" id="id-2-1-windows-authentication-i-le-ba-lant"></a>

![](/files/-Lx6aON3FZ6VdCmVAWQ0)

Server bağlantısını Windows yetkilendirmesiyle kullanıyorsanız aşağıdaki kodu kullanmalısınız.

```
db = pypyodbc.connect(
    'Driver={SQL Server};'
    'Server=serveradi;'
    'Database=veritabaniadi;'
    'Trusted_Connection=True;'
)
```

### 2.2 SQL Server Authentication İle Bağlantı <a href="#id-2-2-sql-server-authentication-i-le-ba-lant" id="id-2-2-sql-server-authentication-i-le-ba-lant"></a>

![](/files/-Lx6aWV-lXIL0M44Qjd9)

Server bağlantısını kullanıcı adı ve şifre ile kullanıyorsanız aşağıdaki kodu kullanmalısınız.

```
db = pypyodbc.connect(
    'Driver={SQL Server};'
    'Server=serveradi;'
    'Database=veritabaniadi;'
    'UID=kullaniciadi;'
    'PWD=parola;'
)
```

## 3. İmleç Oluşturma <a href="#id-3-i-mle-olu-turma" id="id-3-i-mle-olu-turma"></a>

Veritabanı bağlantısı ile komutlarımızı gönderebilmek için aracı bir imleç oluşturmamız gerekiyor. İmleç oluşturmak için aşağıdaki kodları kullanabilirsiniz.

```
imlec = db.cursor()
```

## 4. SQL İşlemleri <a href="#id-4-select-i-lemi" id="id-4-select-i-lemi"></a>

Bağlantımızı ve imlecimizi oluşturduktan sonra temel işlemlerimizi yapmaya başlayabiliriz.

### 4.1 SELECT İşlemi

En çok kullanılan komut olan SELECT ile başlayalım. Bunun için ilk önce veritabanımızda örnek bir tablo oluşturalım. Ben kullanicilar isimli tabloyu oluşturmak ve basit olması için sadece id, ad, soyad, yas sütunlarını kullanmak istiyorum. İlk başta örnek olarak 2-3 tane veride ekleyebilirsiniz:

![](/files/-Lx6aZn8xVc7O4S3QNuo)

Tablomuz ve örnek verilerimiz hazırsa sorgu kodumuzu hemen gönderelim:

```
imlec.execute('SELECT * FROM Kisiler')
```

Bu isteğin ardından dönen sonuçları (dizi olarak döner) bir değişkene aktarmamız gerekiyor. Bunun içinde aşağıdaki gibi bir eşitleme yapıyoruz:

```
kullanicilar = imlec.fetchall()
```

Artık tablomuzdaki kullanıcılarımızı bir değişkene atadık ve sıra ekrana yazdırmaya geldi. Bunun için foreach döngümüzü kullanarak dönen diziyi ekrana yazdırıyoruz:

```
for i in kullanicilar:
    print(i)
```

Ekran çıktımız şu şekilde olacaktır:

![](/files/-Lx6ahCtS8SFY0DfdOKc)

Eğer dönen sonuçları daha detaylı kullanmak istiyorsanız sütun isimlerini kullanarak ekrana yazdırabilirsiniz. Bunun için:

```
for i in kullanicilar:
    print("isim: " + i['ad'] + " " + i['soyad']  + " --- " + "Yaş: " + str(i['yas']) )
```

Ekran çıktımız şu şekilde olacaktır:

![](/files/-Lx6aje9FC3kiL_wR-vn)

!! Tek bir satır çekmek için **`fetchall()`** yerine **`fetchone()`** fonksiyonunu kullanabilirsiniz.

Özet olarak execute fonksiyonu ile hangi komutu gönderirseniz dönen sonuçlar komutun çıktısı olacaktır. Sizlerde istediğiniz komutları yukarıdaki örnekteki gibi gönderebilirsiniz.

### 4.2 INSERT İşlemi

Tablomuza yeni bir kullanıcı eklemek istediğimizde kullanmamız gereken kod yapısı aşağıdaki gibidir:

```
komut = 'INSERT INTO Kisiler VALUES(?,?,?)'
veriler = ('Özlem','ÖZ',25)

sonuc = imlec.execute(komut,veriler)
db.commit()
```

Tablonuza baktığınızda kullanıcınızı eklenmiş göreceksiniz.

![](/files/-Lx6appaQ-UTFvwt3IkJ)

Yukarıdaki kodda **?** ile göndereceğimiz değerleri belli ediyoruz. Tablomuzda ad,soyad ve yas sütunları olduğu için **?** ile belirlediğimiz değişkenleri bir sonraki parametrede yazarak gönderiyoruz `(id sütununu identity ve auto increment bir değer ayarladığım için kendi komutumda id değeri göndermeye gerek yok)`. Yani insert işleminin kabaca syntax yapısı şu şekildedir:

imlec.execute = **(SQL Komutu,Değişkenler)**

En önemli kısmına gelirsek te **db.commit()** ile yaptığımız değişiklikleri veritabanına ileterek insert işlemini gerçekleştiriyoruz. Eğer **`commit()`** işlemini yapmazsanız insert işlemleriniz gerçekleşmez!

### 4.3 UPDATE İşlemi

Şimdi geldik tablomuzdaki mevcut bir değeri güncellemeye. Bu işlem için `UPDATE` komutunu kullanacağız. Aşağıdaki örneği hemen incelemeye başlayabilirsiniz:

```
sonuc = imlec.execute('UPDATE Kisiler SET yas = ? WHERE id = ?',(50,1))
db.commit()

print(str(sonuc) + " kullanıcı güncellendi")
```

Bu işlemin sonucunda ekran çıktılarımız şu şekilde olacaktır:

![](/files/-Lx6ave7B96MJ1607OwP)

Gördüğünüz gibi klasik `Update` komutumuzu gönderdik ve işin kritik noktası olan **commit()** ile işlemlerimizi başarıyla tamamladık. Artık sıradaki işlemimize geçebiliriz.

### 4.4 DELETE İşlemi

Tablomuzdan bir değer silmek istersek `DELETE` komutunu kullanabiliriz. Hemen örneğimizi görelim.

```
sonuc = baglanti.execute('DELETE FROM Kisiler WHERE id = ?',(7,))
db.commit()

print(str(sonuc) + " kullanıcı silindi")
```

Tablomuza baktığımızda kullanıcının silinmiş olduğunu göreceksiniz

## 5. SONUÇ <a href="#id-7-sonu" id="id-7-sonu"></a>

Bu yazımızda Python ile MSSQL veritabanı bağlantısını ve temel işlemleri nasıl yapabileceğimizi öğrendik. Bunu yaparken de işin temelinin SQL komutlarımızı sorunsuz bir şekilde hazırlayıp **execute()** fonksiyonuyla bağlantısını tamamladığımız veritabanımıza göndermek olduğunu gördünüz. Sizde daha gelişmiş işlerinizde yukarıdaki örnekleri baz alabilir, takıldığınız yerleri aşağıya yorum bırakarak sorabilirsiniz.


# # Python PostgreSQL Veritabanı

Python PostgreSQL veritabanı işlemlerini öğreniyoruz.

&#x20;**PostgreSQL**; güçlü, açık kaynak kodlu, nesne ilişkisel ve tüm işletim sistemlerinde çalışabilen gelişmiş bir veritabanı sistemidir. SQL diliyle birlikte kullanılan PostgreSQL’in verileri güvenli bir şekilde saklama, karmaşık verileri ölçeklendirme, hız, performans gibi bir çok özelliği ve avantajı vardır. PostgreSQL hakkında daha detaylı bilgileri araştırma yaparak öğrenebilirsiniz. Bu yazımızda ise Python ile PostgreSQL kullanımını anlatmaya odaklanacağız.

## 1. `Psycopg2` Kütüphanesinin Kurulması ve Projeye Dahil Etme

Python ve PostgreSQL veritabanı bağlantısı işlemini yapabilmek için birçok modül mevcuttur. Biz bunların arasında daha yaygın bir kullanıma sahip olan `Psycopg2` kütüphanesini kullanacağız. Maddelere dökersek ise `Psycopg2` kütüphanesi kullanmamızın sebepleri arasında başlıca şunlar vardır;

* Psycopg2, PostgreSQL için en popüler python modülüdür.
* Birçok Python ve Postgres frameworku ile hali hazırda kullanılan kütüphanedir.
* Python 3 ve Python 2 sürümleri ile sorunsuz çalışır

Özet bilgilerden sonra ilk işimiz `Psycopg2` modülünü kurmak olsun.

```python
pip install psycopg2
```

Artık kütüphanemizi kurduğumuza göre projemize kütüphaneyi dahil edebiliriz. Bunu yapabilmek için dosyamızın en üstüne aşağıdaki kodu ekleyelim:

```python
import psycopg2
```

Kütüphaneyi indirip projemize dahil ettikten sonra artık örneklerimize başlayabiliriz.

## 2. PostgreSQL Veritabanı Bağlantısı

Artık veritabanımıza bağlantımızı yapacak bilgileri oluşturmanın zamanı geldi. Bunun için aşağıdaki kod blogunu ekleyerek kullanıcı adı, şifre ve veritabanı adını kendinize göre düzenlemelisiniz:

```python
db = psycopg2.connect(user = "kullanici_adi",
                      password = "sifre",
                      host = "localhost",
                      port = "5432",
                      database = "veritabani_adi")
```

## 3. İmleç Oluşturma

Veritabanı bağlantısı ile komutlarımızı gönderebilmek için aracı bir imleç oluşturmamız gerekiyor. İmleç oluşturmak için aşağıdaki kodları kullanabilirsiniz.

```python
imlec = db.cursor()
```

Buraya kadar olan işlemlerin doğruluğunu test etmek için aşağıdaki komut ile bağlantı bilgilerimizi ekrana yazdıralım.

```python
print( db.get_dsn_parameters() )
```

Ekran çıktımız aşağıdaki gibi olmalıdır.

![](/files/-M3bXI0Zk0KELCGoA3rM)

Python ile PostgreSQL veritabanı bağlantısını başarıyla yaptıktan sonra artık işlemlerimize geçebiliriz.

## 4. CREATE İle Tablo Oluşturma İşlemi

Temel işlemlerden başladığımıza göre ilk olarak üzerinde çalışabileceğimiz basit bir tablo oluşturalım ve bu tablonun adını `isimler` olarak belirleyelim. Tablomuzun yapısı ve bu tabloyu oluşturacak `CREATE` komutu şu şekilde olacaktır.

| SÜTUN ADI | TİP     | ÖZELLİKLER                  |
| --------- | ------- | --------------------------- |
| id        | integer | Primary Key, Auto Increment |
| ad        | text    | Not NULL                    |
| soyad     | text    | Not NULL                    |

```python
komut_CREATE = """ CREATE TABLE isimler(
                id SERIAL PRIMARY KEY,
                ad TEXT NOT NULL,
                soyad TEXT NOT NULL
                );
                """

imlec.execute(komut_CREATE)
db.commit()
```

Burada SQL komutumuzu yazdıktan sonra `execute()` fonksiyonu ile çalıştırıyoruz ve değişikliklerin veritabanı üzerinde de yapılması için `commit()` fonksiyonu ile işlemi tamamlıyoruz.

![](/files/-M3bXThJ-5Z_1SVqZFmG)

Tablomuz hazır, temel işlemlere başlayabiliriz.

## 5. INSERT İle Tabloya Veri Ekleme İşlemi

Oluşturduğumuz `isimler` tablosuna diğer başlıklarda kullanmak üzere birkaç örnek veri ekleyelim. Bunun için `INSERT` komutunu kullanıyoruz.

```python
komut_INSERT = "INSERT INTO isimler(ad,soyad) VALUES('Fatih','TÜRK');"

imlec.execute(komut_INSERT)
db.commit()
```

Bu şekilde birkaç satır ekleyelim ve tablomuzu kontrol edelim.

![](/files/-M3bX_VOD_w-D70-hU9C)

## 6. SELECT İle Tablodan Verileri Alma İşlemi

En çok kullanılan komut olan `SELECT` ile devam edelim. Bunun için örnek olarak oluşturduğumuz `isimler` tablosunu çekerek ekrana yazdıralım:

```python
komut_SELECT = "SELECT * FROM isimler;"
imlec.execute(komut_SELECT)

liste = imlec.fetchall()
for i in liste:
    print(i)
```

Bu komut ile ekran çıktımız şu şekilde olacaktır.

![](/files/-M3bXh71-6Txp1PbRM-V)

`fetchall()` fonksiyonu ile `execute()` fonksiyonu sayesinde işlediğimiz SQL komutunun çıktısını bir diziye atmış olduk. Bu diziyi de for döngüsü ile ekrana yazdırdık. Dönen dizide sütun isimlerine göre yazdırma işlemi yapmak istiyorsak ta aşağıdaki komutu kullanabiliriz.

```python
komut_SELECT = "SELECT * FROM isimler;"
imlec.execute(komut_SELECT)

liste = imlec.fetchall()
for i in liste:
    print("ID:",i[0]," | ","AD:",i[1]," | ","SOYAD:",i[2]," | ")
```

Ekran çıktımız ise şu şekilde olacaktır.

![](/files/-M3bXnOOgzK1bu-nSIzc)

**NOT:** Sorgu sonucunda tüm satırları çekmek için `fetchall()`, tüm satırlar yerine tek satır almak istiyorsanız `fetchone()`, belirli sayıda satır çekmek istiyorsanız da `fetchmany(SIZE)` fonksiyonunu kullanabilirsiniz.

## 7. UPDATE İle Veri Güncelleme İşlemi

Şimdi geldik tablomuzdaki mevcut bir değeri güncellemeye. Bu işlem için `UPDATE` komutunu kullanacağız. Aşağıdaki örneği hemen incelemeye başlayabilirsiniz:

```python
komut_UPDATE = "UPDATE isimler SET ad='Abdullah' WHERE id=1;"

imlec.execute(komut_UPDATE)

db.commit()
```

`id` sütun değeri 1 olan hücrede ki "Furkan" değerini "Abdullah" ile değiştirdiğimiz komut sonucu tablomuz şu şekilde olacaktır.

![](/files/-M3bXwrdiK5dgmIykHBz)

## 8. DELETE İle Veri Silme İşlemi

Tablomuzdan bir değer silmek istersek `DELETE` komutunu kullanabiliriz. Hemen örneğimizi görelim.

```python
komut_DELETE = "DELETE FROM isimler WHERE id=2;"

imlec.execute(komut_DELETE)

db.commit()
```

Ardından tablomuzun yeni hali şu şekilde olacaktır.

![](/files/-M3bY1ldKw4ojgc6Ywn7)

## 9. SONUÇ

Bu yazımızda Python ile PostreSQL veritabanı bağlantısını ve temel işlemleri nasıl yapabileceğimizi öğrendik. Bunu yaparken de işin temelinin SQL komutlarımızı sorunsuz bir şekilde hazırlayıp `execute()` fonksiyonuyla bağlantısını tamamladığımız veritabanımıza göndermek olduğunu ve ardından işlemlerin veritabanı kısmında da gerçekleşmesi için `commit()` ettiğimizi gördünüz. Sizde daha gelişmiş işlerinizde yukarıdaki örnekleri baz alabilir, takıldığınız yerleri aşağıya yorum bırakarak sorabilirsiniz.


# 🐿️ Go

Bu sayfadan Go programlama dili hakkında birçok ders içeriğine ücretsiz ulaşabilirsiniz.


# Go Giriş

Her geçen popülerliği hızlıca artan dillerinden biri olan Go derslerine giriş yapıyoruz

Her zaman olduğu gibi **"Merhaba Dünya",** artık an itibari ile Go programlama derslerine başlıyoruz. Bunun için ilk olarak Go nedir, nerelerde kullanılır, neden tercih etmeliyim gibi soruları cevaplandırarak eğitimimize başlayabiliriz.

## 1. Go Nedir?

&#x20;**Go**, diğer adıyla **Golang** 2007 yılında adımları atılan, 2009 itibariyle açık bir şekilde adı dile getirilen, 2012 ortalarına doğru **Go 1.0**‘a ulaşan, arkasında Ken Thompson, Rob Pike ve Robert Griesiemer gibi geliştiricilerin bulunduğu ve Google tarafından desteklenen, basitliği ve sunduğu performansla öne çıkan, oldukça genç sayılabilecek, açık kaynak bir [programlama dili](https://github.com/golang). “Go severler” kendilerini **gopher** olarak nitelendiriyorlar. **Gopher**, TCP/IP protokolü olmasına karşın logonun da sembolize ettiği amerikan yersincabı (kemirgen).

![Go dili maskotu olan sincap (Gopher)](/files/-M3_UXxXsmZSWdqkR1fR)

## 2. Go İle Neler Yapılabilir?

* &#x20;Go dilinin birincil amacı sistem programlamalarının yapılmasıdır. Aktif biçimde sunucu tarafında kullanılması için geliştirilen Go’yu, sunucu ve alt sistemler geliştirmek için harika bir dil olarak görebiliriz.&#x20;
* Go web için hem hızlı geliştirme hem de yüksek performansıyla kaliteli projeler üretmenizi sağlayabilir
* Henüz kısıtlı örneklerle karşımıza çıkıyor olmasına rağmen Google’ın, Go’yu mobil işletim sistemi Android’de kullanma planı vardır. Gelecekte Go’yu bilen geliştiriciler sadece sunucu ve sistem tarafındaki işleri halletmekle kalmayarak, kendi Android mobil uygulamalarını da Go ile verimli biçimde geliştirebilecekler.
* Go gömülü sistemlerde kullanılan bir programlama dili olarak da karşımıza çıkabilir. Geliştirici topluluğunun büyük bir bölümü buna inanıyor olsa bile, gömülü sistemlerde hali hazırda süregelen C ve C++ haçlı savaşları nedeniyle bunu şimdilik kestirmek tam olarak mümkün olmayabilir.

## 3. Neden Go Kullanmalıyım?

* Go'da bir işi yapmanın genellikle sadece bir yolu vardır. Bu da herkes tarafından anlaşılan düzenli kodlar ve düzen demek.
* Go tek bir dosya'ya derleniyor. Bir tane binary'yi kopyalamak yeterli. Özetle mevcut kodunuzu onlarca sunucuya sorunsuzca yerleştirebilirsiniz.
* Karışık şöz dizimi kurallarından kurtulabilirsiniz. Go'da sadece 25 tane keyword var (C de 37 tane var; C++ da 84 var ve sayı gittikçe artıyor)
* Basit ve geriye dönük uyumluluğu ayrı bir avantajı.
* Eşzamanlı çalışma (concurrency), static typed ve garbage collection ise diğer önemli avantajlarından birisi.

## 4. Go Dilini Kimler Kullanıyor?

Avantajlı ve pratik bir programlama dili olması Go dilini dev markaların hedefi haline getirmiştir. Google, Go dili aracılığıyla kullanıcılarına daha hızlı bir internet deneyimi armağan etti. Ancak Google dışında Go dilini kendi sistemini iyileştirmek için kullanan daha farklı teknoloji şirketleri de vardır.

*Bu şirketlerden bazıları:*

* Google
* Amazon
* Dropbox
* Ubuntu
* Facebook
* Twitter
* Apple
* Github
* Koding

{% hint style="info" %}
Go kullanan diğer siteleri görmek için [Tıklayınız](https://github.com/golang/go/wiki/GoUsers). Listede Türkiye'den de birçok firma mevcut.
{% endhint %}


# ⚙️ Go Kurulumu

Bu derste Go programlama dilini yazabilmek için bilgisayarınıza gerekli dosyaları nasıl kurabileceğinizi anlatıyoruz.

Go üzerine küçük bir giriş yaptıktan sonra Go öğrenmek isteyenlerle derslerimize devam ediyoruz. Bu dersimizde kod yazabilmek için hangi dosyaları kurmamız gerekiyor, hangi bileşenleri eklememiz gerekiyor anlatacağız. Öyleyse başlayalım.

## 1. Go Kurulumu

&#x20;Go derleyicisi “gc”, açık kaynak yazılım olarak, **Linux**, **OS X**, **Windows**, bazı **BSD**, **Unix** ve **Mobil** ortamlarda kullanılmak üzere geliştirilmiştir. Kullandığınız platforma uygun kurulum işlemlerini aşağıda bulabilirsiniz.

> Kullanıdığınız platforma uygun Go yükleme paketini indirmek için [Tıklayınız.](https://golang.org/dl/)

### 1.1 Windows Kurulumu

1. Windows kurulum paketini indirme sayfasından indiriniz. \[[Link](https://golang.org/dl/)]
2. İndirdiğiniz dosyayı açarak kurulumu tamamlayınız.

Windows kurulumunu artık tamamladınız. CMD komut istemini çalıştırarak aşağıdaki komutu yazınız ve enterlayınız.

```bash
go version
```

Ardından ekranda aşağıdaki gibi bir çıktı göreceksiniz. Eğer göremiyorsanız Windows "[**Komut Satırında (cmd) Go Çalışmıyor | Python Go Ekleme**](https://kerteriz.net/komut-satirinda-cmd-go-calismiyor/)" yazımızı ziyaret ederek gerekli adımları tamamlayınız.

![Windows Go version komutu çıktısı](/files/-M3a3bGJFK_u0QP4BKt9)

### 1.2 MacOS Kurulumu

1. MacOS kurulum paketini indirme sayfasından indiriniz. \[[Link](https://golang.org/dl/)]
2. İndirdiğiniz dosyayı açarak kurulumu tamamlayınız.

Ardından ortam değişkenlerini ayarlamak için `~/.bash_profile` veya `~/.profile` dosyasını (veya eşdeğerini) düzenleyin. Genellikle `GOROOT`, `GOPATH` ve `PATH` olarak 3 ortam değişkeni ayarlamanız gerekir.

* `GOROOT`, Go paketinin sisteminize yüklendiği konumdur.
* `GOPATH`, çalışma dizininizin konumudur. Örneğin, proje dizinim `~/Projeler/Proje1`

```bash
export GOROOT=/usr/local/go
export GOPATH=$HOME/Projects/Proj1
export PATH=$GOPATH/bin:$GOROOT/bin:$PATH
```

MacOS kurulumunu artık tamamladınız. Terminali çalıştırarak aşağıdaki komutu yazınız ve enterlayınız.

```bash
go version
```

Ardından ekranda aşağıdaki gibi bir çıktı göreceksiniz.

![MacOS Go versiyon çıktısı](/files/-M3a6UAljG_E76moulAa)

### 1.3 Ubuntu Kurulumu

1. Linux için güncel versiyon adresini indirme sayfasından görebilirsiniz. \[[Link](https://golang.org/dl/)]
2. Aşağıdaki komutu çalıştırınız.

```bash
cd /tmp
wget https://dl.google.com/go/go1.14.1.linux-amd64.tar.gz
```

Şimdi indirilen arşivi çıkarın ve sistemde istediğiniz yere kurun. Genelde standartların önerdiği şekilde `/usr/local` dizini altında tutulur.

```bash
sudo tar -xvf go1.14.1.linux-amd64.tar.gz
sudo mv go /usr/local
```

Şimdi Go dil ortamı değişkenlerini `GOROOT`, `GOPATH` ve `PATH` ayarlayalım.

* `GOROOT`, Go paketinin sisteminize yüklendiği konumdur.&#x20;
* `GOPATH`, çalışma dizininizin konumudur. Örneğin, burada dizin `~/go`

Home dizinindeki (`~/`) `.profile` dosyanızı açın ve dosyanın sonuna genel bir değişken ekleyin.

```bash
export GOROOT=/usr/local/go
export GOPATH=$HOME/go
export PATH=$GOPATH/bin:$GOROOT/bin:$PATH
```

Geçerli kabuk oturumunu güncelleyiniz.

```bash
source ~/.profile
```

Bu, terminalinizi yeniden başlatmadan Go komutlarını kullanmanızı sağlar.

Ubuntu kurulumunu artık tamamladınız. Terminali çalıştırarak aşağıdaki komutu yazınız ve enterlayınız.

```bash
go version
```

Ardından ekranda aşağıdaki gibi bir çıktı göreceksiniz.

![Ubuntu Go versiyon çıktısı](/files/-M3aBIUe1iN07hXw7u9H)


# ✏️ Go Syntax

Bu derste Go dilinin yazım kurallarını (syntax) göreceğiz.

Her programlama dilinde olduğu gibi Go da kendine has kod yazım kurallarına sahiptir. Kod yazmaya başlamadan önce bu kuralları öğrenmeniz gerektiğinden bu derste **Go Sytnax** konusunu işliyoruz.

## 1. Zorunlu Paket Ekleme

Go programlama dilinde her program mutlaka `package main` ile başlamalıdır. Go, paketleri başka bir Go programında kullanmamıza izin veriyor ve bu nedenle kodun yeniden kullanılabilirliğini destekliyor. Bir Go programının çalıştırılması main adlı paketin içindeki kodla başlar. Örneğin:

```go
package main

import "fmt"
func main() {
    fmt.Println("Merhaba Dünya!")
}
```

## 2. Kütüphaneler

Go üzerinde bir kütüphane ekleme isterseniz bunu `import` ile yapabilirsiniz.

```go
import "fmt"
import "math/rand"
```

Birden fazla kütüphane ekleyecekseniz aşağıdaki gibi bir kullanım daha kolay olabilir.

```go
import (
    "fmt"
    "math/rand"
)
```

## 3. Süslü Parantezler

Go programlama dili herkes için aynı kullanım tarzını benimsetir. Eğer bir fonksiyon ve döngü için süslü parantez kullanacaksanız bunu yapmanın tek bir yolu vardır. Bu doğru ve yanlış kullanımı aşağıda görebilirsiniz.

{% tabs %}
{% tab title="Doğru Kullanım" %}

```go
func add(x int, y int) int {
return x + y
}
```

{% endtab %}

{% tab title="Yanlış Kullanım" %}

```go
func add(x int, y int) int
{
return x + y
}
```

{% endtab %}
{% endtabs %}

## 4. Ana Fonksiyon

Go dilinde yazdığınız programlarınızı yürütmek istiyorsanız mutlaka `main()` fonksiyonunu kullanmalısınız. Program sadece `main()` içinde yazılan işlevleri çalıştıracaktır.

```go
package main
import "fmt"

func main() {
    fmt.Println("Merhaba Dünya!")
}
```

## 5. Ekrana Veri Yazdırma

Go programlama dilinde giriş çıkış işlemleri (I/O) için `fmt` kütüphanesini kullanırız. Eğer çıktılarınızı ekrana basmak veya kullanıcılardan veri almak istiyorsanız bunun `fmt` kütüphanesi ile nasıl olduğunu görelim.

`fmt.Print()` programı içine aldığı değer ve değişkenleri ekrana yazdırır.&#x20;

{% tabs %}
{% tab title="Go" %}

```go
package main
import "fmt"

func main() {
    //Ekrana tek satırda yazı yazar
    fmt.Print("Merhaba ")
    fmt.Print("Dünya!")
}
```

{% endtab %}

{% tab title="Ekran Çıktısı" %}

```
Merhaba Dünya!
```

{% endtab %}
{% endtabs %}

`fmt.Println()` fonksiyonu ise bu değerleri satır satır yazdırır.

{% tabs %}
{% tab title="Go" %}

```go
package main
import "fmt"

func main() {
    //Ekrana satır satır yazı yazar
    fmt.Println("Merhaba")
    fmt.Println("Dünya!")
}
```

{% endtab %}

{% tab title="Ekran Çıktısı" %}

```
Merhaba
Dünya!
```

{% endtab %}
{% endtabs %}

Birden fazla veriyi tek bir fonksiyonla yazdırmak için `,` ile ayırmanız gerekiyor. `fmt.Print()` tüm değerleri boşluksuz olarak yan yana yazdırırken `fmt.Println()` veriler arasına boşluk koyar.

{% tabs %}
{% tab title="Go" %}

```go
package main
import "fmt"

func main() {        
    fmt.Print("Merhaba","Dünya!")
    fmt.Println("Merhaba","Dünya!")
}
```

{% endtab %}

{% tab title="Ekran Çıktısı" %}

```
MerhabaDünya!
Merhaba Dünya!
```

{% endtab %}
{% endtabs %}

## 6. Kullanıcıdan Veri Alma

Go ile kullanıcılardan girdi alabilmek için fmt kütüphanesinin `Scan()` ve `Scanln()` fonksiyonlarını kullanabiliriz.

{% tabs %}
{% tab title="Go" %}

```go
package main
import "fmt"

func main() {        
    fmt.Print("Adınız: ")    
    
    var ad string
    fmt.Scanln(&ad)
    
    fmt.Println("Merhaba",ad)
}
```

{% endtab %}

{% tab title="Ekran Çıktısı" %}

```
Adınız: İsmet
Merhaba İsmet
```

{% endtab %}
{% endtabs %}


# Temel Dersler

Go programlama dilindeki temel dersleri aşağıdaki başlıklardan sırasıyla takip edebilirsiniz.


# # Go Yorumlar

Go yorumlar (comments) dersini işliyoruz.

Bir kod yazarken en önemli aşamalardan birisi de daha sonra aynı koda baktığınızda ne yazdığını anlayabilmeniz, okuyabilmenizdir. Bunun için programlama dillerinde **yorumlar (comments)** kullanılır. Go dili içinde yorumları nasıl kullanabileceğimizi gelin görelim.

## 1. Tek Satırlık Yorumlar

Tek satırlık yorumları daha kısa notlar için kullanabilirsiniz. Bunun için öncelikle `//` işaretini koymalı ve ardından yorumunuzu yazmalısınız. Örneklerini aşağıda görebilirsiniz:

```go
// Bu bir yorum satırıdır ve işleme alınmaz
```

## 2. Çok Satırlık Yorumlar

Bazı durumlarda birden fazla satırı yorum haline getirmek, uzun açıklamalar girmek isteyebilirsiniz. Bu durumda her satırın başına **`//`** koymaktansa `/*` ve `*/` işaretleri ile kendinize çok satırlı yorum alanı oluşturabilirsiniz.

```go
/* Merhaba,  
bu çok satırlı 
yorum alanıdır. */  
```


# # Go Değişkenler

Go değişkenler (variables) dersini işliyoruz.

Programlama dillerinde elinizde ki sayı, isim, liste gibi ögeleri tutarken değişkenlere ihtiyaç duyarsınız ve **değişkenler (variables)** programlamada en temel ögelerdir. Özetle değişkenler elinizde ki verileri depolamanızı mümkün kılar. Birçok programlama dilinde değişkenleri oluştururken verinin tipini *(sayı mı, karakter mi, dizi mi gibi)* değişken isimlerinin önüne getirdiğiniz belirteçlerle tanımlarsınız. Fakat Go ile oluşturduğunuz değişkenlerde hiçbir ön ek kullanmadan bile değişken oluşturabilirsiniz.

{% hint style="warning" %}
Go programlama dilinde tanımladığınız bir değişkeni program için de kullanmazsanız hata alırsınız. **Go, kullanmayacağınız bir değişken tanımlamanıza izin vermez.** Bu nedenle sadece ihtiyacınız varsa değişken tanımlayınız.
{% endhint %}

## 1. Değişken Tanımlama

Bu dersimizde Go programlama dilinde değişken oluşturmanın birden fazla yöntemini göreceğiz. İlk olarak `var` anahtar kelimesiyle değişken oluşturmayı göreceğiz.

```go
var isim = "Kerteriz"
var yas = 25
```

Dilerseniz `var` kullanımda değişkenlerin tiplerini de belirtebilirsiniz.

```go
var sehir string = "Ankara"
var pi double = 3.14
```

Tabi `var` anahtar kelimesini kullanmadan da değişkenler tanımlayabilirsiniz.

```go
meyve := "Muz"
sayi := 100
```

Bu üç farklı değişken tanımlama formatı için tek satırda çoklu değişken de tanımlayabilirsiniz.

```go
var a, b = "Elma", "Armut"
var x, y, z int = 15, 25, 35
a, b, c := "A", "B", "C"
```

Okuması daha kolay bir değişken tanımlama kullanımı için ise şunu kullanabilirsiniz.

```go
var (
    isim = "Blog"
    yas = 25
    sehir string = "Ankara"
)
```

## 2. Local ve Global Değişkenler

Oluşturduğumuz değişkenler kapsam alanlarına göre `local` ve `global` olarak ikiye ayrılırlar. Eğer `local` bir değişken oluşturursak bu değişkene sadece aynı fonksiyon içinde erişebiliriz. Fakat `global` olarak oluşturulan değişkenlere tüm fonksiyonlardan erişebiliriz.

```go
package main
 
import "fmt"

a := 10  //global değişken
 
func main() {
  var b int = 20  // local değişken
  fmt.Println(b)  // doğru çalışır
}

func f() {
  fmt.Println(a)  // doğru çalışır
  fmt.Println(b)  // hata verir
}
```

Bu örnekte `a` değişkeni fonksiyonların dışında global olarak tanımlandığı için tüm fonksiyonlar rahatlıkla erişebilir. Fakat `b` değişkeni `main()` fonksiyonu içinde tanımlandığı için sadece `main()` fonksiyonu erişebilir.

## 3. Sabit Değişkenler

Go programlama dilinde sabit değişkenleri de kullanabilirsiniz. `const` anahtar kelimesiyle oluşturacağınız sabit bir değişkenin daha sonradan değerini değiştiremezsiniz.

```go
const pi float64 = 3.14
```


# # Go Veri Tipleri

Go veri tipleri (data types) dersini işliyoruz.

Bir önceki dersimizde değişkenlerin ne olduğunu ve nasıl oluşturabileceğimizi öğrendik. Şimdi ise Go programlama dillerinde oluşturduğumuz değişkenlerin hangi tiplerde olabileceklerini göreceğiz.

## 1. Veri Tipi Çeşitleri

Programlamada kullanacağımız verinin tipi çok önemlidir. Çünkü örnek olarak bir muhasebe programında ondalık sayılar kullanmanız gerekirken bunun yerine sadece tam sayılar kullanırsanız büyük sorunlar yaşarsınız. Bunun için kullanabileceğiniz veri tiplerini en başta öğrenmeniz çok önemlidir. Go programlama dilinde kullanabileceğiniz veri tipleri şunlardır;

* **Basit tipler:** `Sayılar` (numbers), `Karakter Dizileri` (strings), `Mantık` (boolen)
* **Çoğul tipler:** `Diziler` (arrays), `Yapılar` (structs)
* **Referans tipler:** `İşaretçiler` (pointers), `Dilimler` (slices), `Haritalar` (maps), `Fonksiyonlar` (fonksiyonlar), `Kanallar` (channels)

İlerleyen derslerimizde tüm veri tiplerini detaylıca inceleyip örneklerini yapacağız.

## 2. Veri Tipini Belirterek Değişken Oluşturma

Bir önceki değişkenler dersimizde oluşturacağımız veri tipi belirterek değişken oluşturmayı öğrenmiştik. Küçük bir tekrar ile değişkenlere nasıl veri tipi belirtebileceğimizi görelim.

```go
var sayi int
var isim string
var kontrol bool
```


# # Go Sayılar

Go sayılar (numbers) dersini işliyoruz.

Go veri tiplerine genel bir baktıktan sonra ilk veri tip kategorimiz olan **Go Sayılar** ile derslerimize devam ediyoruz. Go programlama dilinde sayısal tiplerde birçok veri tipimiz mevcut olup aşağıdaki tablodan bu veri tiplerini inceleyebilirsiniz.

## 1. Integer Sayı Veri Tipleri

Integer sayı veri tipleri **tam sayı değerleri**ni tutarlar. En çok kullanılan Integer tipi `int` olmakla beraber tüm veri tiplerini aşağıda görebilirsiniz.

```go
var x int = 65
var y int = 65325
```

| Veri Tipi   | Hafıza                                                                          | İşaret   | Aralık          |
| ----------- | ------------------------------------------------------------------------------- | -------- | --------------- |
| **int8**    | 8-bit                                                                           | signed   | -128 ► 127      |
| **int16**   | 16-bit                                                                          | signed   | -2^15 ► 2^15 -1 |
| **int32**   | 32-bit                                                                          | signed   | -2^31 ► 2^31 -1 |
| **int64**   | 64-bit                                                                          | signed   | -2^63 ► 2^63 -1 |
| **uint8**   | 8-bit                                                                           | unsigned | 0 ► 255         |
| **uint16**  | 16-bit                                                                          | unsigned | 0 ► 2^16 -1     |
| **uint32**  | 32-bit                                                                          | unsigned | 0 ► 2^32 -1     |
| **uint64**  | 64-bit                                                                          | unsigned | 0 ► 2^64 -1     |
| **int**     | 32-bit veya 64 bit. (Platforma göre int32 veya int64 ile eşit)                  | unsigned | Platforma bağlı |
| **uint**    | 32-bit veya 64 bit. (Platforma göre uint32 veya uint64 ile eşit)                | unsigned | Platforma bağlı |
| **rune**    | 32-bit (int32 ile aynıdır. Unicode karakter kodlarını ifade eder.)              | signed   | -2^31 ► 2^31 -1 |
| **byte**    | 8-bit (int8 ile aynıdır)                                                        | signed   | -128 ► 127      |
| **uintptr** | işaretçi değerinin yorumlanmamış bitlerini saklamak için işaretsiz bir tam sayı | unsigned | -               |

## 2. Float Sayı Veri Tipleri

Float sayı veri tipleri **ondalıklı sayı değerleri**ni tutarlar. Platformunuza göre kullanacağınız Float tipini belirleyebilir ve tüm veri tiplerini aşağıda görebilirsiniz.

{% hint style="info" %}
Sayılarda ki ondalık kısımları `. (nokta)` ile belirtmelisiniz. `, (virgül)` kullanımı hataya sebep olacaktır.
{% endhint %}

```go
var pi float32 = 3.14
var katsayi float64 = -152.65
```

| Veri Tipi   | Hafıza | İşaret | Aralık          |
| ----------- | ------ | ------ | --------------- |
| **float32** | 32-bit | signed | -2^32 ► 2^32 -1 |
| **float64** | 64-bit | signed | -2^64 ► 2^64 -1 |

## 3. Complex Sayı Veri Tipleri

Complex sayı veri tipleri **karmaşık sayı değerleri**ni tutarlar. Bu veri tipi tam ve sanal olmak üzere iki bölümden meydana gelmektedir. Tüm veri tiplerini aşağıda görebilirsiniz.

```go
var a complex128 = complex(6, 2) // (6+2i)
var b complex64 = complex(-9, 2)  // (-9+2i)
```

| Veri Tipi      | Hafıza                      | İşaret | Aralık          |
| -------------- | --------------------------- | ------ | --------------- |
| **complex64**  | 32-bit (tam ve sanal kısmı) | signed | -2^32 ► 2^32 -1 |
| **complex128** | 64-bit (tam ve sanal kısmı) | signed | -2^64 ► 2^64 -1 |

## 4. Sayı Veri Tipleri Arası Dönüşüm

Tanımladığınız sayı veri tipini daha sonradan değiştirmek isterseniz (**Type conversion**), değiştirmek istediğiniz değişkeni dönüştürmek istediğiniz veri tipinin parantezine alarak dönüşümü yapabilirsiniz.

```go
var i int = 42
var f float64 = float64(i)
var u uint = uint(f)
```


# # Go Karakter Dizileri

Go karakter dizileri (strings) dersini işliyoruz.

Her programlama dilinde olduğu gibi Go programlama dilinde de **karakter dizileri** yani **string** değişken tipi büyük önem arz eder. Çünkü tanımlayacağınız birçok değişken string ifadeler içerir. Üstelik string değişken tipleri üzerinden yürütebileceğiniz birçok Go fonksiyonu mevcuttur. Bir `string` veri tipinde değerler **`"`** (çift tırnak) ve `` ` `` (yatay tek tırnak) ifadeleri arasında gösterilir. Ayrıca `string()` fonksiyonu ile de yeni bir `string` değişken oluşturabilirsiniz.

```go
var isim string = "Kerteriz"
var sehir = `Ankara`
ulke := string("Türkiye")
```

Diğer programlama dillerinde `'` (tek çizgi) veya `"""` (üç tırnak) işareti kullanıyor olabilirsiniz ama Go programlama dilinde tek doğru vardır. Bu sebeple yalnızca `"` (çift tırnak) veya `` ` `` (yatay tek tırnak) kullanmanız gerekmektedir.

```go
// DOĞRU
blog := "Kerteriz"

// DOĞRU
blog := `Kerteriz`

// YANLIŞ
sehir := 'Ankara'

// YANLIŞ
arac := """Otobüs"""
```

{% hint style="info" %}
`String` değişken tanımlarken birden fazla satırdan oluşan değerler oluşturabilirsiniz.
{% endhint %}

```go
a := `Merhaba arkadaşlar,
Bu örnekte gördüğünüz gibi,
birden fazla satıra sahip
değişken oluşturabilirsiniz.`
```

Bir `string` tanımlarken değerine atayacağınız metinde `"` işareti varsa **Kaçış Karakteri** olan `\` kullanarak `"` işaretini kullanabilirsiniz.

```go
// YANLIŞ
metin := "okuduğum kitabın adı "1984" idi."

// DOĞRU
metin := "okuduğum kitabın adı \"1984\" idi."
```

## 1. String Değerler Aynı Zamanda Dizidir

Bir **string** veri tipinde değişken oluşturmuşsanız aynı zamanda bir dizi oluşturmuşsunuz demektir. Çünkü ders başlığında da yazdığımız gibi bir string değişken **karakter dizisi** şeklinde veri tipidir. Örneğin " **Kerteriz** " kelimesi `K` , `e` , `r` , `t` , `e` , `r` , `i` , `z` harflerinden meydana gelir. Bunu hemen başka bir örnekle gösterelim:

```go
sehir := "Ankara"

fmt.Println(sehir[0])    //65
fmt.Println(sehir[1])    //110
fmt.Println(sehir[2])    //107
fmt.Println(sehir[3])    //97
fmt.Println(sehir[4])    //114
fmt.Println(sehir[5])    //97
```

{% hint style="info" %}
Dizilerde (ilerleyen derslerde göreceğiz) index her zaman 0 dan başlar. Yani 0.index ilk elemandır.
{% endhint %}

{% hint style="warning" %}
Bu örnekte dönen karakter değerleri ASCII Tablosunda yer alan karakterlerin decimal (ondalık) karşılıklarıdır. Tüm tabloya ulaşmak için [Tıklayınız.](http://www.asciitable.com/)
{% endhint %}

## 2. ASCII Kodundan Karakter İfadesine Dönüştürme

Yukarıda verdiğimiz örnekte karakterlerin ASCII tablosundaki değerini elde ettik. Şimdi ise elimizde bulunan bu ASCII değerinden `string()` fonksiyonu ile nasıl karakteri elde edebileceğimizi göreceğiz.

```go
asciiKod := 65
karakter := string(asciiKod)

fmt.Println(karakter)    // A
```

## 3. Metin Birleştirme ve Toplama

Bazı durumlarda elinizde bulunan string değerleri birbirleriyle birleştirmek ve yan yana eklemek isteyebilirsiniz. Bunun için matematiksel ifade olan **+** işareti kullanılır. Örneklerini aşağıda görebilirsiniz.

```go
ad := "Fatih"
ek := "Sultan"
ad2 := "Mehmet"

sonuc := ad + ek + ad2

fmt.Println(sonuc)    // FatihSultanMehmet
```

String değişkenlerimizi birleştirdik ama araya boşluklarda eklemek istersek direkt değişken yerine metin ekleme işlemi yapabiliriz. Tabi amacınız sadece göstermekse **Println()** fonksiyonunda , kullanarakta yapabilirsiniz.

```go
ad := "Fatih"
ek := "Sultan"
ad2 := "Mehmet"

sonuc := ad + " " + ek + " " + ad2

fmt.Println(sonuc)    // Fatih Sultan Mehmet
fmt.Print(ad,ek,ad2)    // FatihSultanMehmet
fmt.Println(ad,ek,ad2)    // Fatih Sultan Mehmet
```

## 4. Metin Dilimleme (String Parçalama)

Programlamanızı yaparken elinizdeki `string` değişkenlerin belirli bir parçasını kullanmak, başından veya sonundan kırpmak, tersine çevirmek gibi işlemlere tabi tutmak isteyebilirsiniz. İlk olarak elinizdeki metinin bir karakter dizisi olduğunu hatırlayalım.

```go
sehir := "Ankara"

fmt.Print(sehir[0])    //65
fmt.Print(sehir[1])    //110
fmt.Print(sehir[2])    //107
fmt.Print(sehir[3])    //97
fmt.Print(sehir[4])    //114
fmt.Print(sehir[5])    //97

//Tersinede işlem yapabiliriz

fmt.Print(sehir[len(sehir)-1])    //97
fmt.Print(sehir[len(sehir)-2])    //114
fmt.Print(sehir[len(sehir)-3])    //97
fmt.Print(sehir[len(sehir)-4])    //107
fmt.Print(sehir[len(sehir)-5])    //110
fmt.Print(sehir[len(sehir)-6])    //65
```

{% hint style="info" %}
**len()** fonksiyonu bize değişkenin karakter uzunluğunu verir.
{% endhint %}

Öyleyse elimizdeki metin üzerinde x. karakterden y. karaktere kadar kırpma işlemini gerçekleştirelim.

```go
isim := "Kerteriz ile Go öğreniyorum"

// 4. indeksten 10.indekse kadar
fmt.Print(isim[4:10]) // eriz i

// En baştan 10.indekse kadar
fmt.Print(isim[:10]) // Kerteriz i

// 4. indeksten sonuna kadar
fmt.Print(isim[4:]) // eriz ile Go öğreniyorum'

// İki değer de belirtilmemişse tüm stringi al.
fmt.Print(isim[:]) // Kerteriz ile Go öğreniyorum

// Son karaktere kadar al.
fmt.Print(isim[:len(isim)-1]) // kerteriz ile Go öğreniyoru'
```

## 5. String Fonksiyonları

### 5.1 Metinin Karakter Uzunluğunu Öğrenme

Elinizdeki string değişkenin kaç karakterden oluştuğunu öğrenmek için **len()** fonksiyonunu kullanabilirsiniz.

```go
a := "Merhaba Dünya!"

fmt.Print(len(a))     // 14
```

### 5.2 Metindeki Boşlukları ve Özel Karakterleri Temizleme

Bir metinin başındaki ve sonundaki boşlukları ve özel karakterleri temizlemek için **TrimSpace(),** **Trim()**, **TrimLeft()**,  **TrimRight()** fonksiyonlarını kullanabilirsiniz. Fakat öncelikle **strings** kütüphanesini eklemelisiniz.

```go
package main

import (
	"fmt"
	"strings"
)

func main() {

	a := " \t\t Merhaba Dünya! \n "
	
	a = strings.TrimSpace(a)	// Boşlukları ve özel karakterleri temizler
	fmt.Println(a)     // Merhaba Dünya!
	
	a = strings.Trim(a,"\t \n")	// Boşlukları ve belirtilen özel karakterleri temizler
	fmt.Println(a)     // Merhaba Dünya!
	
	a = strings.TrimLeft(a,"\t \n")	// Boşlukları ve belirtilen özel karakterleri metinin başından temizler
	fmt.Println(a)     // Merhaba Dünya!
	
	a = strings.TrimRight(a,"\t \n")	// Boşlukları ve belirtilen özel karakterleri metinin sonundan temizler
	fmt.Println(a)     // Merhaba Dünya!

}
```

### 5.3 Metindeki Tüm Karakterleri Büyük Harfe Çevirme

Elinizdeki metini tamamen büyük harflere çevirmek istiyorsanız **ToUpper()** fonksiyonunu kullanabilirsiniz.

```go
package main

import (
	"fmt"
	"strings"
)

func main() {

	s := "kerteriz"

	fmt.Println(strings.ToUpper(s))		// KERTERIZ

}
```

### 5.4 Metindeki Tüm Karakterleri Küçük Harfe Çevirme

Elinizdeki metini tamamen küçük harflere çevirmek istiyorsanız **ToLower()** fonksiyonunu kullanabilirsiniz.

```go
package main

import (
	"fmt"
	"strings"
)

func main() {

	s := "BLOG"

	fmt.Println(strings.ToLower(s))		// blog

}
```

### 5.5 Metindeki Baş Harfleri Büyük Harfe Çevirme

Elinizdeki metinin sadece baş harflerini büyük harflere çevirmek istiyorsanız **Title()** fonksiyonunu kullanabilirsiniz.

```go
package main

import (
	"fmt"
	"strings"
)

func main() {

	s := "merhaba blog okuyucuları"

	fmt.Println(strings.Title(s))		// Merhaba Blog Okuyucuları

}
```

### 5.6 Metindeki Karakterleri Başka Karakterlerle Değiştirmek

Metindeki bir karakter veya bir kelime grubunu başka bir karakter veya metin grubuyla değiştirmek istediğinizde **Replace()** fonksiyonunu kullanabilirsiniz.

```go
package main

import (
	"fmt"
	"strings"
)

func main() {

	s := "Muz tatlı bir meyvedir."

	fmt.Println(strings.Replace(s,"Muz","Çilek",-1))		// Çilek tatlı bir meyvedir.

}
```

{% hint style="info" %}
Fonksiyonun dördüncü parametresini **-1** verirseniz metindeki bulduğu tüm değişimleri yapar. Fakat **-1** yerine başka bir sayı verirseniz verdiğiniz sayı kadar değişim yapar. Örneğin **2** verirseniz sadece **2** tane değişim işlemi yapar, diğer eşleşmelere ellemez. Ayrıca fonksiyon küçük-büyük harf duyarlıdır.
{% endhint %}

### 5.7 Metini İstenilen Bir Karakterden Bölerek Diziye Atmak

Elinizdeki metini  **Split()** fonksiyonu ile belirlediğiniz bir karakterden bölerek diziye atayabilirsiniz. Aşağıdaki örnekte örnek kullanımını görebilirsiniz.

```go
package main

import (
	"fmt"
	"strings"
)

func main() {

	s := "Kayseri,Nevşehir,Kırşehir İç Anadolu bölgesindedir"
	dizi := strings.Split(s,",")
	
	fmt.Println(dizi)				// [Kayseri Nevşehir Kırşehir İç Anadolu bölgesindedir]
	fmt.Println(len(dizi))	// 3

}
```

### 5.8 Metin İçinde Karakter veya Metin Aramak

Bir metin editöründe nasıl karakter veya metin arayabiliyorsanız Go programlama diliyle de `string` değişkeniniz içinde **Contains()** fonksiyonuyla herhangi bir karakter veya metin arayabilirsiniz.

```go
package main

import (
	"fmt"
	"strings"
)

func main() {

	s := "En sevdiğim hava yağmurlu havadır"
	
	fmt.Println(strings.Contains(s,"mur"))	// true 

}
```

### 5.9 Metin İçindeki Bir Karakterin Kaç Adet Olduğunu Bulmak

Elimizdeki bir metinde bir karakterin kaç adet geçtiğini bulmak için **Count()** fonksiyonunu kullanabiliriz.

```go
package main

import (
	"fmt"
	"strings"
)

func main() {

	s := "Corona ile mücadele için evde kalmalıyız."
	
	fmt.Println(strings.Count(s,"e"))	// 5

}
```

### 5.10 Bir Kelimenin Ne ile Başlayıp Başlamadığını Kontrol Etmek

Doğrulama işlemlerin de işimize yarayacak bir fonksiyon olan **HasPrefix()** ile bir string değişkenin belirlediğimiz bir karakter dizisi ile başlayıp başlamadığını kontrol edebiliriz.

```go
package main

import (
	"fmt"
	"strings"
)

func main() {

	s := "Profesyonel blogculuk için Kerteriz Blog"
	
	fmt.Println(strings.HasPrefix(s,"Pro"))	// true
	fmt.Println(strings.HasPrefix(s,"a"))	// false

}
```

### 5.11 Bir Kelimenin Ne ile Bitip Bitmediğini Kontrol Etmek

Doğrulama işlemlerin de işimize yarayacak başka bir fonksiyon olan **HasSuffix()** ile bir string değişkenin belirlediğimiz bir karakter dizisi ile bitip bitmediğini kontrol edebiliriz.

```go
package main

import (
	"fmt"
	"strings"
)

func main() {

	s := "Profesyonel blogculuk için Kerteriz Blog"
	
	fmt.Println(strings.HasSuffix(s,"og"))	// true
	fmt.Println(strings.HasSuffix(s,"y"))	// false

}
```

### 5.12 Bir Karakterin Metindeki Yerini Bulmak

String değişken üzerinden bir karakterin veya metinin ilk index numarasını bulmak için **Index()** fonksiyonunu kullanabiliriz. Eğer sonuç bulunumazsa -1 dönecektir.

```go
package main

import (
	"fmt"
	"strings"
)

func main() {

	s := "Kerteriz"
	
	fmt.Println(strings.Index(s,"iz"))	// 6
	fmt.Println(strings.Index(s,"t"))		// 3
	fmt.Println(strings.Index(s,"a"))		// -1
		
}
```

### 5.13 Dizi Elemanlarını Bir Karakterle Birleştirmek

Dizi elemanlarını herhangi bir karakter veya metin ile birleştirmek isterseniz **Join()** fonksiyonunu kullanabilirsiniz.

```go
package main

import (
	"fmt"
	"strings"
)

func main() {
	
	fmt.Println(strings.Join([]string{"a", "b", "c"}, "-"))	// a-b-c

}
```

### 5.14 Bir İfadeyi İstenilen Sayıda Tekrar Ettirmek

String değişkenimizi istediğimiz adette tekrar ettirerek çoğaltabiliriz. Bunun için **Repeat()** fonksiyonunu kullanabilirsiniz.

```go
package main

import (
	"fmt"
	"strings"
)

func main() {
	
	fmt.Println(strings.Repeat("xXx",3))	// xXxxXxxXx
}
```


# # Go Boolen

Go boolen dersini işliyoruz.

Matematikte mantık dediğimizde aklımıza nasıl **doğru** ve **yanlış** terimleri geliyorsa Go programlama dilinde de **`bool`**  veri tipinde **True** ve **False** değerleri karşımıza çıkıyor. Herhangi iki değeri karşılaştırdığınızda veya bir ifadenin doğrulunu kontrol ederken **bool** veri tipini kullanabilirsiniz.

```go
var (
    durum bool = true
    kontrol bool = false
)

fmt.Println(durum)        // true
fmt.Println(kontrol)       // false
```

Değişkenlerimizi `bool` veri tipinde oluşturup değerlerini atadık. Herhangi bir değer atamadan bile koşullar bize `bool` veri tipinde sonuç döndürürler.

```go
fmt.Println(5 > 4)        // true
fmt.Println(5 == 4)       // false
fmt.Println(5 < 4)        // false
```

Örnekteki gibi Go ile bir durumu kontrol ettiğinizde size True veya False olarak cevap döner. Aynı şekilde **if** kontrol durumları ile de `bool` ifadeleri kullanabilirsiniz.

```go
a := 10
b := 20

if a > b {
		fmt.Println("a büyüktür b den")
} else {
	fmt.Println("b büyüktür a dan")
}

// b büyüktür a dan
```

{% hint style="info" %}
&#x20;Bir `bool` veri tipindeki değişkene hiçbir değer atamazsanız öntanımlı olarak **false** değerini döndürür.
{% endhint %}

```go
var x bool

fmt.Println(x)    // false
```


# # Go Diziler & Dilimler

Go diziler (arrays) ve dilimler(slices) dersini işliyoruz.

**Dizi**, homojen öğeleri bellekte saklamak için kullanılan belirli veya sonsuz uzunluklu bir değişken tipidir. **Dilimler** ise elimizde ki dizilerden parçalayarak oluşturduğumuz yeni dizilerdir.

Go programlama dilindeki diziler diğer programlama dillerine çok benzer. Dizilerde aynı türden bir veri koleksiyonunu depolamamız gerekir. Yani hem `int` hem `string` veri tipini aynı dizide bulunduramayız.&#x20;

Go programlama dilinde bir diziyi birden fazla yöntemle oluşturabiliriz.

```go
// boş dizi oluşturma
var hayvanlar []string
cicekler := []string{}

// boş ve eleman sayısını belirleyerek dizi oluşturma
var sayilar [3]int
var sehirler [10]string

// başlangıçta elemanlara sahip dizi oluşturma
rakamlar := [81]int{1,2,3,4,5,6}
var rastgele1 []int = []int{1,2,3,4,5,6}
var rastgele2 [6]int = [6]int{1,2,3,4,5,6}

// eleman sayısını dizi boyutu kadar belirleme
sira := [...]int{1,2,3,4,5,6}

// make() fonksiyonu ile belirli uzunlukta dizi 
a := make([]int, 5)

// make() fonksiyonu ile belirli uzunlukta (0) ve kapasitede (5) dizi 
b := make([]int, 0, 5)
```

{% hint style="info" %}
**`[]`** içinde kalan değer dizimizin eleman sayısını belirtir. Eğer belirtmezseniz sonsuz kapasiteli dizi elde edersiniz. Fakat eleman sayısını belirtirseniz int diziler için öntanımlı olarak **`0`**, string diziler için **`""`** elemanı dizinin elemanlarına tanımlanır.
{% endhint %}

Yukarıdaki bilgi notunda verdiğimiz bilgiyi görelim.

```go
var hayvanlar []string
cicekler := []string{}
var sayilar [3]int
var sehirler [10]string
rakamlar := [10]int{1,2,3,4,5,6}
var rastgele1 []int = []int{1,2,3,4,5}
var rastgele2 [5]int = [5]int{1,2,3,4,5}
sira := [...]int{1,2,3,4,5,6}
a := make([]int, 5)
b := make([]int, 0, 5)

fmt.Println(hayvanlar)    // []
fmt.Println(cicekler)     // []
fmt.Println(sayilar)      // [0 0 0]
fmt.Println(sehirler)     // [         ]
fmt.Println(rakamlar)     // [1 2 3 4 5 6 0 0 0 0]
fmt.Println(rastgele1)     // [1 2 3 4 5]
fmt.Println(rastgele2)     // [1 2 3 4 5]
fmt.Println(sira)         // [1 2 3 4 5 6]
fmt.Println(a)            // [0 0 0 0 0]
fmt.Println(b)            // []
```

Oluşturduğumuz `liste` değişkeninin tipini kontrol edelim.

```go
package main

import (
    "fmt"
    "reflect"
)

func main() {

    var liste []string    
    fmt.Println(reflect.TypeOf(liste))    // []string

}
```

## 1. Dizi Elemanlarına Erişim

Go programlama dilinde elinizdeki bir listenin elemanlarına ulaşabilmek için indeksleri kullanmalısınız. Aşağıdaki örnekle indeksleri nasıl kullanacağınızı gösterelim.

```go
liste := [...]string {"Sal","Vapur","Feribot","Korvet","Fırkateyn"}

fmt.Println(liste[0])    // Sal
fmt.Println(liste[1])    // Vapur
fmt.Println(liste[2])    // Feribot
fmt.Println(liste[3])    // Korvet
fmt.Println(liste[4])    // Fırkateyn
```

{% hint style="warning" %}
İndeks her zaman **0** dan başlar. Yani bir listede ilk elemanın indeksi 0 dır.
{% endhint %}

## 2. Dizi Elemanını Değiştirmek

Dizi elemanlarını görüntüledikten sonra eğer bir elamanı değiştirmek istiyorsanız direkt ilgili indekse değer atayabilirsiniz.

```go
liste := [...]string {"Sal","Vapur","Feribot","Korvet","Fırkateyn"}

liste[0] = "Sandal" 
liste[4] = "Uçak Gemisi"

fmt.Print(liste)    // [Sandal Vapur Feribot Korvet Uçak Gemisi]
```

## 3. Dizi Eleman Sayısını Bulmak

Dizilerin eleman sayısını bulabilmek için **len()** fonksiyonunu kullanmalıyız.

```go
liste := [...]string {"Sal","Vapur","Feribot","Korvet","Fırkateyn"}

fmt.Print(len(liste))    // 5
```

## 4. Bir Listeden Yeni Liste Oluşturma (Slice)

Elimizde mevcut olan bir listeden indeks belirterek yeni bir liste oluşturabiliriz. Bu işleme **dilimleme** yani **slice** denir. Örneğin mevcut listenin 2.indeksinden 5.indeksine kadar ( *5 dahil değil* ) olan elemanlarla yeni bir liste oluşturalım.

```go
var liste []string = []string{"a", "b", "c", "d", "e", "f", "g"}

yeniliste1 := liste[2:5]
yeniliste2 := liste[:3]
yeniliste3 := liste[1:]
yeniliste4 := liste[:]

fmt.Println(yeniliste1) // [c d e]
fmt.Println(yeniliste2) // [a b c]
fmt.Println(yeniliste3) // [b c d e f g]
fmt.Println(yeniliste4) // [a b c d e f g]
```

{% hint style="info" %}
Bu şekilde yeni liste oluştururken **`[x:y]`** ifadesinde **x** dahil, **y** dahil değildir. Ayrıca indeksin **0** dan başladığını unutmayınız!
{% endhint %}

## 5. Diziye Yeni Eleman Ekleme

Diziler ile çalışırken dizinin sonuna rahatlıkla yeni bir eleman ekleyebilirsiniz. Bunun için **append()** fonksiyonunu kullanacağız.

```go
meyveler := []string{"kivi", "çilek", "muz", "nar"}

meyveler = append(meyveler, "karpuz")

fmt.Println(meyveler)     // [kivi çilek muz nar karpuz]
```

Tek bir eleman yerine yeni bir dizide ekleyebilirsiniz.

```go
sayilar := []int{99, 138, 652}
rakamlar := []int{3, 5, 7, 9}

sayilar = append(sayilar, rakamlar...)

fmt.Println(sayilar)     // [kivi çilek muz nar karpuz]
```

## 6. Diziden Bir Elemanı Çıkarmak

Diziden eleman çıkarmak için belirli bir fonksiyon yok ama aşağıdaki örneği inceleyebilirsiniz.

```go
harfler := []string{"A", "B", "C", "D", "E"}

	// 2.indexte yer alan C elemanını çıkarmak
	harfler = append(harfler[:2], harfler[3:]...)

	fmt.Println(harfler)		// [A B D E]
```

## 7. Liste Kopyalamak ve Çoğaltmak

Elimizde olan bir listeyi kopyalayarak çoğaltmak istiyorsak kopyalayacağımız diziyi direkt yeni diziye eşitleyebiliriz.

```go
harfler := []string{"A", "B", "C", "D", "E"}
var harfler_yeni []string

harfler_yeni = harfler

fmt.Println(harfler_yeni)     // [A B C D E]
```


# # Go Harita

Go haritalar (maps) dersini işliyoruz.

Harita, **anahtar** ve **değer** çiftlerinden oluşan bir koleksiyondur. Dizilerde verileri sadece index numaralarıyla tutabilirken **`map`** kullanımında indexler yerine anahtar değerler atayabiliriz.

Harita (map) veri tipini kullanabilmek için önce haritayı oluşturmalı, ardından başlatmalıyız.&#x20;

```go
var x map[string]int        // map oluşturma

x = make(map[string]int)    // map başlatma
```

{% hint style="info" %}
Bir **`map`** oluşturduğunuzda öntanımlı olarak **`nil`** olur. **`nil`**,  **pointers, interfaces, maps, slices, channels** ve **function** veri tiplerindeki boş değeri temsil eder. Tıpkı integer bir değişkenin öntanımlı değerinin 0 olması gibi. Bunun için oluşturduğumuz haritayı başlatmamız gerekir.
{% endhint %}

Örnek olarak anahtar tipini `string`, değer tipini `int` ayarladıktan sonra artık elemanları oluşturmaya başlayabilirsiniz.&#x20;

```go
x["sayi"] = 10
x["adet"] = 55

fmt.Println(x)    // map[adet:55 sayi:10]
```

Gördüğünüz gibi dizilerden farklı olarak indexler yerine istediğimiz değerleri kullanarak key oluşturabiliyoruz.

## 1. Harita Elemanlarına Erişim

Anahtar ve değer çiftiyle oluşturduğumuz haritalarda yer alan elemanlara sadece anahtarı kullanarak erişebiliriz.

```go
package main

import (
	"fmt"
)

func main() {

	var ogrenci map[string]string
	ogrenci = make(map[string]string)
	
	ogrenci["ad"] = "Deniz"
	ogrenci["soyad"] = "Barış"
	ogrenci["cinsiyet"] = "E"

	fmt.Println(ogrenci["ad"])				// Deniz
	fmt.Println(ogrenci["soyad"])			// Barış
	fmt.Println(ogrenci["cinsiyet"])	// E
}

```

## 2. Harita Elemanını Silmek

Haritadan bir elemanı silmek için delete() fonksiyonunu anahtar değer ile beraber kullanabilirsiniz.

```go
var ogrenci map[string]string
ogrenci = make(map[string]string)
	
ogrenci["ad"] = "Deniz"
ogrenci["soyad"] = "Barış"
ogrenci["cinsiyet"] = "E"

delete(ogrenci,"cinsiyet")

fmt.Println(ogrenci)	// map[ad:Deniz soyad:Barış]
```

## 3. Haritada Bir Anahtarın Olup Olmadığını Kontrol Etmek

Haritada anahtarın olup olmadığını kontrol edebiliriz. Eğer ilgili anahtara sahip bir değer varsa **true**, yoksa **false** döner.

```go
var ogrenci map[string]string
ogrenci = make(map[string]string)
	
ogrenci["ad"] = "Deniz"
ogrenci["soyad"] = "Barış"


deger1, kontrol1 := ogrenci["cinsiyet"]
deger2, kontrol2 := ogrenci["ad"]

fmt.Println("Mevcut mu?",kontrol1,"Değeri:",deger1)	
// Mevcut mu? false Değeri: 

fmt.Println("Mevcut mu?",kontrol2,"Değeri:",deger2)
// Mevcut mu? true Değeri: Deniz
```


# # Go Operatörler

Go operatörler (operators) dersini işliyoruz.

Diğer tüm programlama dillerinde olduğu gibi Go programlama dilinde de operatörler değişkenler ve değerler üzerinde işlem gerçekleştirmek için kullanılırlar. Buradaki işlem birçok kategoriye sahiptir. Şimdi bu kategorileri yazalım ve ardından tek tek inceleyelim;&#x20;

* Aritmetik (arithmetic) operatörler
* Atama (assignment) operatörleri
* Karşılaştırma (comparison) operatörleri
* Mantıksal (logical) operatörler
* Bit (bitwise) operatörleri

## 1. Aritmetik Operatörler

Go aritmetik (arithmetic) operatörler sayılar üzerinde matematiksel işlemler yapılırken kullanılırlar. `a=5` ve `b=2` değişkenleri üzerinden aşağıdaki örnek kullanımları inceleyebilirsiniz.

| Operatör | Açıklama     | Örnek            |
| -------- | ------------ | ---------------- |
| +        | Toplama      | a + b     => 7   |
| -        | Çıkarma      | a - b      => 3  |
| \*       | Çarpma       | a \* b     => 10 |
| /        | Bölme        | a / b     => 2.5 |
| %        | Mod Alma     | a % b    => 1    |
| ++       | Bir Artırma  | a++       => 6   |
| --       | Bir Eksiltme | a--         => 4 |

{% hint style="info" %}
`++` ve `--` ifadeleri Go programlama dilinde sadece **statement** ile kullanılabilir. **Expression** olarak kullandığınızda hata alırsınız. İkisi arasındaki fark için [Tıklayınız.](https://medium.com/@burcus/expression-ve-statement-fark%C4%B1-293105692ccd)
{% endhint %}

{% tabs %}
{% tab title="Doğru Kullanım (Statement)" %}

```go
a++
fmt.Print(a)
```

{% endtab %}

{% tab title="Yanlış Kullanım (Expression)" %}

```go
fmt.Print(a++)
```

{% endtab %}
{% endtabs %}

## 2. Atama Operatörleri

Go Atama operatörleri değerleri değişkenlere atarken kullanırlar. Tabi bu atamaları yaparken aynı zamanda aritmetik operatörleri de kullanarak pratik kod yazabilirsiniz. `a=5` ve `b=2` değişkenleri üzerinden aşağıdaki örnek kullanımları inceleyebilirsiniz.

| Operatör | Açıklama          | Eş Kullanım |
| -------- | ----------------- | ----------- |
| =        | Eşittir           | a = b       |
| +=       | Toplayarak Eşitle | a = a + b   |
| -=       | Çıkararak Eşitle  | a = a - b   |
| \*=      | Çarparak Eşitle   | a = a \* b  |
| /=       | Bölerek Eşitle    | a = a / b   |
| %=       | Mod Alarak Eşitle | a = a % b   |
| &=       | Bit AND İşlemi    | a = a & b   |
| \|=      | Bit OR İşlemi     | a = a \| b  |
| ^=       | Bit XOR İşlemi    | a = a + b   |

## 3. Karşılaştırma Operatörleri

Go karşılaştırma (comparison) operatörleri ile sayılar üzerinde büyük, küçük ve eşit ifadeleriyle karşılaştırma yapabilirsiniz. `a=5` ve `b=2` değişkenleri üzerinden aşağıdaki örnek kullanımları inceleyebilirsiniz.

| Operatör | Açıklama      | Eş Kullanım           |
| -------- | ------------- | --------------------- |
| ==       | Eşit mi       | a == b      // False  |
| !=       | Eşit değil mi | a != b       // True  |
| >        | Büyük mü      | a > b        // True  |
| <        | Küçük mü      | a < b        // False |
| >=       | Büyük eşit mi | a >= b      // True   |
| <=       | Küçük eşit mi | a <= b      // False  |

## 4. Mantıksal Operatörleri

Go mantıksal (logical) operatörler ile şartlı durumları birleştirebilirsiniz. `a=5` ve `b=2` değişkenleri üzerinden aşağıdaki örnek kullanımları inceleyebilirsiniz.

| Operatör | Açıklama                    | Eş Kullanım                            |
| -------- | --------------------------- | -------------------------------------- |
| &&       | Her iki durumda doğruysa    | a < 5 && b < 10             // True    |
| \|\|     | Herhangi bir durum doğruysa | x < 5 \|\| x == 10             // True |
| !        | Durumu ters çevir           | !(a < 5 && b < 10)        // False     |

## 5. Bit Operatörleri

Go bit (bitwise) operatörler ile değişkenleri karşılaştırarak `AND` , `OR` , `XOR` , `NOT` , `Sağa Kaydırma` ve `Sola Kaydırma` işlemlerini gerçekleştirebilirsiniz. Örnek kullanımları aşağıdan inceleyebilirsiniz.&#x20;

| Operatör | Açıklama      |
| -------- | ------------- |
| &        | AND işlemi    |
| \|       | OR işlemi     |
| ^        | XOR işlemi    |
| <<       | Sola kaydırma |
| >>       | Sağa kaydırma |

**&** operatörü ile elinizdeki bir sayıyı başka bir sayı ile bit düzeyinde **AND** işlemine tabi tutabilirsiniz. Örnek kullanım aşağıdadır:

```go
a := 3
// bit değeri: 0011

b := 5
// bit değeri: 0101

a &= b

//         0011
//(AND)    0101
//-------------
//         0001


fmt.Println(a)    // 1
```

**`|`** operatörü ile elinizdeki bir sayıyı başka bir sayı ile bit düzeyinde **OR** işlemine tabi tutabilirsiniz. Örnek kullanım aşağıdadır:

```go
a := 3
// bit değeri: 0011

b := 5
// bit değeri: 0101

a |= b

//         0011
//(OR)     0101
//-------------
//         0111


fmt.Println(a)    // 7
```

**`^`** operatörü ile elinizdeki bir sayıyı başka bir sayı ile bit düzeyinde **XOR** işlemine tabi tutabilirsiniz. Örnek kullanım aşağıdadır:

```go
a := 3
// bit değeri: 0011

b := 5
// bit değeri: 0101

a ^= b

//          0011
//(XOR)     0101
//--------------
//          0110


fmt.Println(a)    // 6
```

**`>>`** operatörü ile elinizdeki bir sayının bit değeri üzerinden sağa kaydırma işlemi yapabilirsiniz. Soldan gelen yeni bitle ise 0 değerini alır. Örnek kullanım aşağıdadır:

```go
a := 5
// bit değeri: 0101

a >>= 2
// yeni bit değeri: 0001

fmt.Println(a)    //1
```

**`<<`** operatörü ile elinizdeki bir sayının bit değeri üzerinden sola kaydırma işlemi yapabilirsiniz. Sağdan gelen yeni bitle ise 0 değerini alır. Örnek kullanım aşağıdadır:

```go
a := 13
// bit değeri: 1101

a <<= 5
// yeni bit değeri: 110100000

fmt.Println(a)    //416
```


# # Go Koşul Durumları

Go koşul durumları (if else) dersini işliyoruz.

Bilgisayar teknolojilerinin temelinde nasıl ki 0 ve 1 durumları varsa programlama dillerinin de temelinde algoritmaları oluşturan `if` ve `else` durumları vardır. Bu dersimizde de önemli bir aşama olan if..else konusunu anlatacağız.&#x20;

Koşul ifadeleri programımızda durumları kontrol etmemizi ve programlamanın seyrini değiştirmeye yarar. **`if`** , **`else`** ve **`else if`** terimleriyle mantıksal ifadeleri kullanarak bir durumun koşulu sağlaması durumunda çalışmasını gerçekleştirebiliriz.

```go
a := 25 
b := 50

if b > a {
    fmt.Println("b büyüktür a dan")
}
```

Örnekte gördüğünüz gibi eğer `b > a` koşulu doğruysa program if durumunun içine girer ve ekrana metni yazdırır.

{% hint style="info" %}
Koşul durumlarında **==** , **!=** , **<** , **<=** , **>** , **>=** ifadelerini kullanabilirsiniz.
{% endhint %}

Eğer **if** koşulunun gerçekleşmediği durumda başka bir durumun gerçekleşmesini istiyorsak bunu **else** terimi ile gerçekleştirebiliriz.

{% tabs %}
{% tab title="Doğru Kullanım" %}

```python
sayi := 3

if sayi % 2 == 0{
    fmt.Println(sayi , "çift sayıdır")
} else{
    fmt.Println(sayi , "tek sayıdır")
}
```

{% endtab %}

{% tab title="Yanlış Kullanım" %}

```go
sayi := 3

if sayi % 2 == 0{
    fmt.Println(sayi , "çift sayıdır")
} 
else{
    fmt.Println(sayi , "tek sayıdır")
}
```

{% endtab %}
{% endtabs %}

{% hint style="warning" %}
**`else`** komutu, **`if`** komutu süslü parantezinin bittiği satıra yazılmalıdır. Aksi halde Syntax hatası alırsınız.
{% endhint %}

Bu örnekte 3 sayısının tek mi çift sayı olduğunu kontrol ediyoruz. Eğer sayımız çift ise if durumu, değilse else durumu çalışacaktır. Programımızda yeri geldiğinde birden fazla durumu kontrol etmek durumunda kalabiliriz. Bunun içinde Python programlama dilinde **else if** terimi devreye girer.

```python
yas := 65

if yas < 18 {
    fmt.Println("Ergensiniz")
} else if yas >= 18 && yas < 66 {
    fmt.Println("Gençsiniz")
} else if yas >= 66 && yas < 79 {
    fmt.Println("Orta yaşlısınız")
} else if yas >= 80 && yas < 100 {
    fmt.Println("Yaşlısınız")
} else {
    fmt.Println("Yaş grubunuzu belirleyemedik!")
}
```

Örnekte olduğu gibi artık sadece **if** ve **else** ile kalmadık ve ara durum koşullarını da **elif** ile kullandık.

## 1. İç İçe If Else Kullanımı

Koşullarınızı yazarken iç içe if ve else koşullarınızı yazarak daha detaylı koşul durumları oluşturabiliriz.

```python
x := 41

if x > 10 {
  fmt.Println("Sayı ondan büyük")
  if x > 20 {
    fmt.Println("Sayı yirmiden büyük")
  } else {
    fmt.Println("Sayı yirmiden küçük")  
  }
}
```


# # Go Döngüler

Go döngüler (loops) dersini işliyoruz.

Go programlama dilinde kullanabileceğimiz tek döngü çeşidi vardır. Bu döngü **for** döngüsüdür.

{% hint style="info" %}
Golang programlama dilinde **while** döngüsü bulunmamaktadır.
{% endhint %}

Döngüler sayesinde programımızda bir dizi elemanları boyunca veya belirlediğimiz iki değer arasında bir süreç oluşturup programımızın tekrarlı çalışmasını sağlayabiliriz. Öyleyse **for** döngüleri ile başlayalım.


# # Go For Döngüsü

Go döngüler (for) konusunu işliyoruz.

Go programlama dilinde bir dizi veya belirlediğiniz iki sayı arasında döngü oluşturmak istediğinizde **for** terimini kullanırsınız. Programlama da önemli bir yeri olan **for** için örnek kullanımları hemen görelim.&#x20;

## 1. While Tarzı Döngü Oluşturmak

İlk örneğimizde diğer programla dillerinde yer alan **while** döngüsüne benzer bir kullanım ile bir aralıkta döngüyü çevirebiliriz.

```go
package main

import "fmt"

func main() {
	deger := 0
	for deger < 5 {
		fmt.Println(deger)
		deger++
	}
}
```

## 2. İki Sayı Arasında Döngü Oluşturmak

Belirlenen iki sayı arasında da döngü ayarlayabiliriz.

```go
package main

import "fmt"

func main() {
	for i := 0; i < 10; i++ {
		fmt.Println(i)
	}
}
```

## 3. Dizi Elemanları Üzerinde Döngü Oluşturmak

Elimizde olan bir liste üzerinde de `for` döngüsüyle gezinerek elemanlarını ekrana yazdırabiliriz.

```go
package main

import "fmt"

func main() {

	var sehirler []string = []string{"Ankara","İstanbul","Kayseri"}

	for i := 0; i < len(sehirler); i++ {
		fmt.Println(sehirler[i])
	}

}
```

## 4. For Döngüsünü Durdurma

Döngümüz ilerlerken istediğimiz bir durumda durdurabilmek için **break** komutunu kullanırız. Go **break** komutunu gördüğünde döngüyü durdurarak döngüden çıkar.

```go
package main

import "fmt"

func main() {

	var sayilar []int = []int{1,2,3,4,5}

	for i := 0; i < len(sayilar); i++ {
		
		if i == 1 {
			break
		}
	
		fmt.Println(sayilar[i])
	}

}
```

## 5. For Döngüsünde Atlama Yapmak

Döngümüzü bir koşul ile durdurabileceğimizi gördük. Şimdi ise yine bir koşul ile döngüde ki o durumu atlayabiliriz ve döngünün diğer aşamasına geçebiliriz. Bunun için **continue** terimini kullanabiliriz.

```go
package main

import "fmt"

func main() {

	var sayilar []int = []int{1,2,3,4,5}

	for i := 0; i < len(sayilar); i++ {
		
		if i == 1 {
			continue
		}
	
		fmt.Println(sayilar[i])
	}

}
```


# # Go Fonksiyonlar

Go fonksiyonlar (functions) dersini işliyoruz.

Fonksiyonlar, sadece çağrıldıklarında çalışan kod bloklarıdır. Bir fonksiyon ile tanımladığınız belirli komutlarınız, yeri geldiğinde çağrılarak, parametreler gönderilerek kullanılır ve istenilirse size bir değer döndürür.

## 1. Fonksiyon Oluşturmak ve Çağırmak

Go programlama dilinde bir program oluşturabilmek için **`func`** terimini kullanırız ve ardından fonksiyon ismini yazarız.

```go
func ornekFonksiyon() {
	fmt.Println("Merhaba!")
}
```

Oluşturduğumuz bir fonksiyonu programımızın istediğimiz yerinde çağırabiliriz. Bunun için sadece fonksiyon ismini belirtmemiz yeterlidir.

```go
ornekFonksiyon()
```

## 2. Fonksiyon Parametreleri

Oluşturduğumuz fonksiyona parametre göndererek işleme sokmak istiyorsak, fonksiyonumuzu oluştururken parantezlerin arasında bu parametreleri belirtmeli ve fonksiyonu çağırırken ilgili parametre değerleri ile çağırmalıyız.

```go
package main

import (
	"fmt"
)

func selamVer(isim string,yas int){
    fmt.Println("Merhaba,",isim,yas,"yaşındadır")
}

func main() {
	selamVer("Yunus",24)
}

// Merhaba, Yunus 24 yaşındadır
```

Örnekte gördüğünüz gibi fonksiyona iki adet parametre alacağını söyledik ve fonksiyonu çağırırken bu iki parametrenin de değerini gönderdik. Fonksiyon da gelen bu parametreleri ilgili yerlere otomatik olarak yerleştirdi. Bir örnek daha yapalım.

```go
package main

import (
	"fmt"
)

func kareAlma(x int){
    fmt.Println(x*x)
}

func main() {
	kareAlma(7)
}

// 49
```

{% hint style="info" %}
Fonksiyonlarınız da istediğiniz kadar parametre kullanabilirsiniz fakat ilgili fonksiyonu çağırırken tüm parametrelere değer atadığınızdan emin olmalısınız.
{% endhint %}

```go
func toplama(x int,y int){
    fmt.Println(x+y)
}

func main() {
	toplama(7)   // Hata verir! Parametre eksik
}
```

{% hint style="info" %}
Fonksiyon parantezi içerisine değişken tanımlanırken eğer tüm değişkenlerin türleri aynı ise sadece en sağdaki değişkenin tipini belirtmeniz yeterlidir.
{% endhint %}

```go
package main

import "fmt"

func islem(sayi int) (x, y int) { 
	x = sayi / 2
	y = sayi * 2
	return //Burada sadece return yazıyor
}

func main() {
	fmt.Println(islem(10))
}
```

Burada `sayi` değişkeni fonksiyonun değişkeni, `x` ve `y` değişkenleri ise return ile dönecek olan değişkenlerdir.

## 3. Fonksiyon Dönüş Değeri Belirleme

Fonksiyonlarımızın çağrıldıkları zaman çalıştıklarını artık öğrendik. Ayrıca bu fonksiyonlar ile ekrana çıktı verebildiğimizi de yukarıdaki örneklerde gördünüz. Şimdi ise oluşturduğumuz fonksiyonlara **return** ile dönüş değeri döndürmesini söyleyeceğiz ve fonksiyonlarımızı çalışması için çağırdığımızda bize bir değer döndürecek.

```go
func toplama(x int,y int) int{
    return x+y
}

func main() {
	var toplam = toplama(7,8)
	fmt.Println(toplam)						// 15
}
```

Bu basit örneğimizde fonksiyonumuzun toplama işlemini yaparak bize **return** ile sonucu döndürmesini istedik. Böylece fonksiyon sonucunu bir değere atayarak veya direkt ekrana yazdırarak işlem sonucumuzu öğrenmiş olduk.

```go
func selamVer() string{
    return "Merhaba!"
}
    
func main() {
	fmt.Println(selamVer())    // Merhaba!
}     
```


# # Go İşaretçiler

Go işaretçiler (pointers) dersini işliyoruz.


# C++

Bu sayfadan C++ ve frameworkleri hakkında birçok ders içeriğine ücretsiz ulaşabilirsiniz.


# C++ Giriş

En popüler programlama dillerinden biri olan C++ derslerine giriş yapıyoruz

**"Merhaba Dünya",** artık an itibari ile C++ programlama derslerine başlıyoruz. Bunun için ilk olarak C++ nedir, nerelerde kullanılır, neden tercih etmeliyim gibi soruları cevaplandırarak eğitimimize başlayabiliriz

## 1. C++ Nedir?

**C++**, 1979'da Bell Labs'da Bjarne Stroustrup tarafından geliştirilen **derlemeli** ve **nesne yönelimli** bir **orta düzey** programlama dilidir. C++, Windows, Mac OS ve UNIX'in çeşitli sürümleri gibi çeşitli platformlarda çalışır.

{% hint style="info" %}
Yazılan bir kodu başka bir programlama diline çevirdikten sonra çalıştıran ve koddaki hataları yakalayan, kodun iyileştirilmesini daha kod çalıştırmadan yapan çeviricilere **derleyici (compiler)**, kodu satır satır veya bloklar halinde çalıştırıp sırası gelmeyen satırları hiç çalıştırmayan, sırası gelmeyen satırlardaki hataları göremeyen ve kodun bütününe ait iyileştirmeleri yapamayan çeviricilere de **yorumlayıcı (interpreter)** adı verilmektedir. Detaylı bilgi için [bakınız.](https://techdifferences.com/difference-between-compiler-and-interpreter.html)
{% endhint %}

## 2. C++ İle Neler Yapılabilir?

* C++ dilinin orta seviyeli bir dil olmasından dolayı diğer yüksek seviyeli programlama dillerinden gerekli optimizasyon yapıldığında daha performanslı olduğu söylenebilir.
* Nesne Yönelimli Programlama desteği sayesinde modern programlamaya imkan vermesinden dolayı Sürücü yazılımları, Oyun, Görüntü işleme, İşletim sistemleri gibi hızın önemli olduğu yerlerde kullanılır.
* C++ öğretme ve araştırma için yaygın olarak kullanılır çünkü temel kavramların başarılı bir şekilde öğretilmesi için yeterince temizdir.
* OpenCV görüntü işleme kütüphanesi ilk olarak C ile geliştirilmiş daha sonra C++ ile geliştirilmeye devam etmektedir.
* Unity ve bir çok oyun motoru C++ ile geliştirilmiştir.
* TensorFlow, Apache MXNet gibi Yapay Zeka araçları da C++ ile geliştirilmiştir.
* Chrome tarayıcısı ve Chrome, Node.js V8 JavaScript moturu C++ ile geliştirilmiştir.
* Benzer şekilde bir çok programlama diline ait derleyici yine C++ ile geliştirilmiştir.
* C ++, donanımın gerçek zamanlı kısıtlamalarla doğrudan manipülasyonuna dayanan aygıt sürücülerini ve diğer yazılımları yazmak için çok kullanışlıdır.
* Apple Macintosh veya Windows çalıştıran bir PC  C++ ile yazıldığı için kullanılan işletim sistemleri üzerinde çalışan uygulamalar yazmak için kullanılabilir.

## 3. Neden C++ Kullanmalıyım?

* **C++ programlama dili**ni tercih etmenizin birçok sebebi olabilir ancak ben burada önemli gördüğüm avantajlarını sizlerle paylaşacağım. İşte **C++ dili**ni seçmenin sebepleri;
* **C++ dili** genel amaçlı bir programlama dilidir. İsterseniz düşük seviyede kodlar isterseniz de yüksek seviye kodlar kullanarak programlama yapabilirsiniz.
* **C++,** **doğrusal**, **yapısal** aynı zamanda da **nesne tabanlı** bir programlama tekniklerine imkân tanır.
* Günümüzde ki güncel işletim sistemi olan **Windows**, **Linux**, **Mac OS** gibi işletim sistemleri C++ ile yazılmıştır. Sürücüler veya donanımlarla ilgili iletişim kuran programlar yapılacaksa **en iyi** **tercih C++ dili** olacaktır.
* **C++**, en karmaşık ve zorlu algoritmaların altından kolaylıkla kalkabilir. Tamamen **nesne tabanlı** ve **modern** bir programlama dilidir.
* **C++ dili** ile isterseniz düşük seviyede kod isterseniz de yüksek seviyede kodlar yazabilirsiniz. Yani isterseniz sadece donanım seviyesinde işlemler dahi yapabilirsiniz. Buda size hem kolaylık hem de büyük bir esneklik sağlayacaktır.
* **C++** günümüzdeki teknolojiye çok iyi bir şekilde ayak uydurmayı başarmıştır ve &#x43;**++ dili**ni kullanarak, hem donanım tabanlı **mikro kontrolör uy** hem de **.NET** teknolojisini kullanarak **masaüstü**, **web** ve **mobil uygulamalar** geliştirebilirsiniz.
* **C++** dilini kullanan büyük bir kitle vardır. Buda sizlere hem çalışma ve öğrenme kaynağı açısından yeterli doküman bulmayı hem de bir sorun yaşadığınızda kolay bir şekilde yardım bulabileceğinizi göstermektedir.


# ⚙️ C++ Kurulumu

C++ ortamının nasıl kurulacağını öğreneceğiz.

Genel bir bilgilendirmeden sonra C++ için gerekli iki ana bileşeni kurmaya başlıyoruz. C++ ile kodlama yapabilmeniz için gereken araçlar şunlardır;

1. **C++ Editör**
2. **C++ Compiler**

## 1. C++ Editör

C++ yazabilmek için bir metin editörü kullanmamız gerekiyor. Bu editör seçimini kendiniz belirleyebilirsiniz. Tabi seçebileceğiniz editörlerden bazıları şu şekildedir; `Not Defteri`, `Notepad++`, `Visual Studio Code`, `Eclipse`, `Netbeans`, `Dev C++`. Metin editörünün adı ve sürümü farklı işletim sistemlerine göre değişebilir. Siz istediğiniz editörü kullanabilirsiniz.

{% hint style="info" %}
C++ programını yazdığınız dosya **kaynak dosya** olarak adlandırılır ve uzantısı genellikle `.cpp`, `.cp` veya `.c` uzantılıdır
{% endhint %}

## 2. C++ Compiler

C++ Compiler veya diğer adıyla Derleyici, kaynak kodunuzu çalıştırılabilir bir programa çevirir.

Çoğu C ++ derleyicisi, kaynak kodunuza hangi uzantıyı verdiğinizi umursamaz, ancak aksi belirtilmediyse, çoğu varsayılan olarak .cpp kullanır.

En çok kullanılan derleyiciler aşağıdadır.&#x20;

* MinGW / GCC
* Borland c++
* Dev C++
* Embracadero
* Clang
* Visual C++
* Intel C++
* Code Block

## 3. Windows C++ Compiler Kurulumu

Bu derslerimizde biz MinGW / GCC derleyiciyi kullanacağız. Sizde GCC’yi Windows’a yüklemek için MinGW’yi yükleyebilirsiniz. MinGW’yi kurmak için MinGW ana sayfasına, [www.mingw.org](http://www.mingw.org/) adresindeki Downloads sayfasına gidiniz ve güncel sürümü indiriniz.

> İndirme sayfasına gitmek için [Tıklayınız.](https://osdn.net/projects/mingw/releases/)

`mingw-get-setup.exe` isimli dosyayı indiriniz.

![](/files/-M1295yNkyqh3jwPxc60)

Ardından aşağıdaki resimde olduğu gibi kutucukları seçiniz ve **Installation** altında yer alan **Apply Changes** seçeneğini tıklayarak açılan pencerede **Apply** butonunu kullanınız. Seçmeniz gereken kutucukları tikli şekilde aşağıda gösterdiklerimdir;

* [x] mingw-developer-toolkit-bin
* [x] mingw32-base-bin
* [ ] mingw32-gcc-ada-bin
* [ ] mingw32-gcc-fortran-bin
* [x] mingw32-gcc-g++-bin
* [x] mingw32-gcc-objc-bin
* [x] msys-base-bin

![](/files/-M12ApdekeD3hfcZdwAN)

Kurulumu tamamladıktan sonra Path ekleme işlemi yaparak derleyiciyi sisteme tanıtacağız ve gcc derleyiciyi kullanmaya başlayacağız. Bunun için Bilgisayarıma sağ tıklayarak `Özellikler`e giriniz ve sırasıyla "`Gelişmiş Sistem Ayarları`" - "`Gelişmiş" sekmesi` "-  "`Ortam Değişkenleri`" penceresinde "`Sistem Değişkenleri`" bölümünde yer alan "`Path`" değişkenine MinGW nin kurulu olduğu dizindeki **bin** klasörünün adresini ekliyoruz.

![](/files/-M14PqP1XZ6vepGvwmg3)

![](/files/-M14PuTrMMAE6He_hsqr)

Bu işlemlerden sonra Windows komut satırından gcc, g++, ar, ranlib, dlltool ve diğer birçok GNU araçlarını çalıştırabileceksiniz. Örnek olarak uzantısını .cpp olarak kaydettiğiniz bir metine belgesine aşağıdaki komutları yapıştırınız.

{% code title="ilkKod.cpp" %}

```cpp
#include <iostream>
#include <cstdlib>
 
using namespace std; 

int main() 
{ 
    cout<<"Merhaba!"<<endl; 
    system("PAUSE");
    return 0; 
}
```

{% endcode %}

Kaynak kodlarının olduğu dosyanın bulunduğu dizinde komut istemini açarak aşağıdaki komutu çalıştırınız.

```bash
g++ ilkKod.cpp -o ilkKod.exe
```

Komutu çalıştırdığınızda dosyanızın bulunduğu dizinde `ilkKod.exe` isimli dosyanın oluştuğunu göreceksiniz. Dosyayı açarsanız karşınıza **Merhaba!** yazısının çıktığını ve kurulum aşamasını başarıyla geçtiğinizi anlayabilirsiniz.


# ✏️ C++ Syntax

Bu derste C++ dilinin yazım kurallarını (syntax) göreceğiz.

Her programlama dilinde olduğu gibi C++ da kendine has kod yazım kurallarına sahiptir. Kod yazmaya başlamadan önce bu kuralları öğrenmeniz gerektiğinden bu derste **C++ Sytnax** konusunu işliyoruz.

## 1. Temel Kavramlar

C++ programlama dilinde temel kavramların anlamlarını öğrenerek başlayalım.

* **Nesne (Object):** Nesneler durumlar ve davranışlara sahip olan varlıklardır. Örn: Personel bir nesne olabilir. Yaşı ve Cinsiyeti vardır. Belirli bir görevi yapar.
* **Sınıf (Class):** Nesnelerin durum ve davranışlarını bir şablonda belirtmek için kullanılan nesneden bağımsız soyut yapılardır. Nesneler bu şablonlardan örneklenir.
* **Method:** Temel olarak bir davranışı ifade eder.  Bir sınıf bir çok methodu içerebilir. Verilerin işlendiği ve tüm eylemlerin yürütüldüğü bölümlerdir.
* **Özellikler (Instance Variables):** Her nesne kendine özgü niteliklere sahiptir. Nesnelere ait durumlar tanımlanan bu niteliklerde tutulmaktadır.

## 2. C++ Program Yapısı

Her programlama dilinde olduğu gibi "Merhaba Dünya" ile dilin yapısını inceleyelim.

```cpp
#include <iostream>
using namespace std;
 
// main() main programı çalıştıran ana metotdur. 
int main() {
   cout << "Merhaba Dünya"; //Ekrana merhaba dunya yazdırılır
   return 0;
}
```

**`#`** ifadesi ile başlayan ifadeler C++’da önişlemci olarak bilinir.  **#include** ile C++ için gerekli olan kütüphane bilgileri tanımlanır ve programa dahil edilir. **\<iostream>** kütüphanesi temel işlemler için gerekli bir kütüphanedir.

**using namespace std;** (std değiştirilebilir) Nesne yönelimli programlama için Namespace tanımlaması yapmak için kullanılır. İsteğe bağlıdır. Yukarıda tanımlanmazsa kullanılan method ile tanımlanır.

**main()** program çalıştırmanın başladığı yerdir. Her C ++ programının main() olarak bilinen bir yöntemi olması gerekir. Bilgisayarınızdaki programın yürütülmesine başladığınızda uygulamanın giriş noktası olarak anılır. i**nt** kısmı yöntemin dönüş türüdür. Fonksiyon adından sonraki boş parantezler `()`, bunun bir fonksiyon olduğunu ve herhangi bir bağımsız değişken gerektirmediğini, başka bir deyişle, değerleri iletmek için hiçbir parametrenin olmadığını gösterir. &#x20;

Ayrıca  tek satırlık yorumlar **//** ile başlar ve satırın sonunda durur.

Sonraki satır **cout << “Merhaba Dünya”;** Ekranda **Merhaba Dünya** yazısını göstermek için kullanılır. Özetle ekrana **cout <<** ile çıktılarınızı verebilirsiniz.

Son olarak da  **return 0;** programı sonlandırmak için dönüş değeri 0 girilip sonlandırılır.&#x20;

## 2. C++ Derleme ve Çalıştırma

C++ editörünüz ile yazdığınız kodları çalıştırabilmek için dosya uzantısını **.cpp** olarak kaydediniz. (Örn: test.cpp)

Bir komut istemi açın ve dosyayı kaydettiğiniz dizine gidin. Bunun için bulunduğunuz dizindeki pencerenin adres yerine **cmd** yazarak enterlayabilir veya direkt **cmd** üzerinden `cd` komutuyla ilgili dizine gidebilirsiniz. (Örn: cd Desktop)

Artık komut satırına aşağıdaki kodları yazarak programınızı derleyebilir ve aynı dizinde oluşacak olan **.exe** uzantılı dosyanız ile programınızı çalıştırabilirsiniz.

```bash
g++ test.cpp -o test.exe
```

## 3. Noktalı Virgüller ve Bloklar

C++ da ifadeler noktalı virgülle sonlandırılır.  Yazılan her satırın sonuna noktalı virgül koymak gerekir.

```cpp
a=10;
b=a;
kareAl(5);
```

Bloklar, süslü parantezler ile gösterilir ve mantıksal olarak kümelenmiş ifadeleri göstermek için kullanılır.

```cpp
{
   cout << "Merhaba Dunya";
   return 0;
}
```

## 4. C++ Tanımlayıcılar

Bir C ++ tanımlayıcısı; bir değişken, işlev, sınıf, modül veya herhangi bir kullanıcı tanımlı ögeyi tanımlamak için kullanılan bir addır.  Bir tanımlayıcı;

* A’dan Z’ye veya a’dan z’ye Türkçe karakter olmayan harflerden,
* Alt çizgi (\_)
* Sayılardan

oluşabilir.

{% hint style="warning" %}
**C++**, tanımlayıcılarda @, % gibi noktalama karakterlerine ve tanımlayıcı adının sayı ile başlamasına izin vermez. Ayrıca tanımlayıcı büyük küçük harf duyarlıdır.  sayi1 ile Sayi1, SAYI1 tanımlamaları aynı değildir.
{% endhint %}

Örnek değişkenler;&#x20;

* Sayi1
* \_ad
* ornek
* Toplam
* say10

## 5. C++ Anahtar Kelimeler

Aşağıdaki anahtar kelimeler C++ tarafından rezerve edilmiştir. C++’da tanımlayıcı yazarken bu anahtar kelimeler **kullanılamaz.** :exclamation:&#x20;

|               |           |                   |          |
| ------------- | --------- | ----------------- | -------- |
| asm           | else      | new               | this     |
| auto          | enum      | operator          | throw    |
| bool          | explicit  | private           | true     |
| break         | export    | protected         | try      |
| case          | extern    | public            | typedef  |
| catch         | false     | register          | typeid   |
| char          | float     | reinterpret\_cast | typename |
| class         | for       | return            | union    |
| const         | friend    | short             | unsigned |
| const\_cast   | goto      | signed            | using    |
| continue      | if        | sizeof            | virtual  |
| default       | inline    | static            | void     |
| delete        | int       | static\_cast      | volatile |
| do            | long      | struct            | wchar\_t |
| double        | mutable   | switch            | while    |
| dynamic\_cast | namespace | template          |          |


# C++ Temel Dersler

C++ programlama dilindeki temel dersleri aşağıdaki başlıklardan sırasıyla takip edebilirsiniz.


# # C++ Yorum Satırları

C++ Yorumlar (Comments) konusunu işliyoruz.

Yorum Satırları, C++ koduna ekleyebileceğiniz açıklayıcı ifadelerdir. Kaynak kodu okuyanlar için açıklayıcı ifadeleri barındırır. Bütün programlama dillerinde buna benzer yorum satıları mevcuttur.

C++, tek satırlı ve çok satırlı yorumları yazılabilir. C++’ın derleyicisi tarafından yorum satırları bir açıklama olarak görür ve dikkate almaz.

Tek ve çok satırlı yorumlar aşağıdaki gibi yapılır.

```cpp
// merhaba, burası yorum satırıdır.
 
/* 
Cok satirli yorum ile
birden fazla satırı yoruma ayırabilirsiniz
*/
```

Örnek olarak:

```cpp
// tek satirlik bir yorum
#include <iostream>
 // Tek satirlik baska bir yorum,
int main(){
    /*
    Bu kisim birden fazla yorum yapmak icin kullanilir.
    Bu yorumun ikinci satiri
    */
    return 0;
}
```


# # C++ Veri Tipleri

C++ Yorumlar (Data Types) konusunu işliyoruz.

Program yazarken, çeşitli bilgileri saklamak için bir dizi değişkenler kullanırız. Değişkenler, değerleri  bellekte saklamak için ayrılmış bellek bölümleridir. Bu nedenle, bir değişken oluşturduğunuzda hafızada yer ayırmış oluruz.

Karakterler, metinler, tamsayı, ondalıklı sayılar, boolean(true/false) gibi çeşitli veri türlerine ait bilgilerini saklamak isteyebilirsiniz. Değişkenin veri türüne bağlı olarak, işletim sistemi hafızayı ilgili boyutta ayırır.

## 1. Temel Veri Türleri

C++ programcıya, kullanıcı tanımlı veri türlerinin yanı sıra, zengin bir çeşitlilik sunar. Aşağıdaki tabloda yedi temel C++ veri türü  aşağıdaki işaretleri alarak bellekte çeşitli boyutlarda alan tahsis edilmesini sağlar.

* signed
* unsigned
* short
* long

| Tip                | Bellek Boyutu | Değer Aralığı                  |
| ------------------ | ------------- | ------------------------------ |
| char               | 1 byte        | -127 – 127 yada 0 – 255        |
| unsigned char      | 1 byte        | 0 – 255                        |
| signed char        | 1 byte        | -127 – 127                     |
| int                | 4 byte        | -2147483648 – 2147483647       |
| unsigned int       | 4 byte        | 0 – 4294967295                 |
| signed int         | 4 byte        | -2147483648 – 2147483647       |
| short int          | 2 byte        | -32768 – 32767                 |
| unsigned short int | Range         | 0 – 65,535                     |
| signed short int   | Range         | -32768 – 32767                 |
| long int           | 4 byte        | -2,147,483,648 – 2,147,483,647 |
| signed long int    | 4 byte        | long int gibi                  |
| unsigned long int  | 4 byte        | 0 – 4,294,967,295              |
| float              | 4 byte        | +/- 3.4e +/- 38 (\~7 digits)   |
| double             | 8 byte        | +/- 1.7e +/- 308 (\~15 digits) |
| long double        | 8 byte        | +/- 1.7e +/- 308 (\~15 digits) |
| wchar\_t           | 2 yada 4 byte | 1 geniş karakter               |

Aşağıdaki örnekte **`sizeof()`** metodu ile veri tiplerinin bellekte ne kadar alan kapladığını görebilirsiniz. Mevcut örnekte yeni bir satıra geçmek için **`endl`** ve birden fazla veri eklemek için de **`<<`** sembolü kullanılmıştır.

{% tabs %}
{% tab title="Komutlar" %}

```cpp
#include <iostream>
using namespace std;
 
int main() {
    cout <<"Veri Boyutlari" << endl;
    cout << "char : " << sizeof(char) << endl;
    cout << "int : " << sizeof(int) << endl;
    cout << "short int : " << sizeof(short int) << endl;
    cout << "long int : " << sizeof(long int) << endl;
    cout << "float : " << sizeof(float) << endl;
    cout << "double : " << sizeof(double) << endl;
    cout << "wchar_t : " << sizeof(wchar_t) << endl;
    
    system("PAUSE");
    return 0;
}
```

{% endtab %}

{% tab title="Ekran Çıktısı" %}

```
Veri Boyutlari
char : 1
int : 4
short int : 2
long int : 4
float : 4
double : 8
wchar_t : 2
```

{% endtab %}
{% endtabs %}

{% hint style="info" %}
**`system("PAUSE")`** komutu ile programınızın çalıştıktan sonra hemen kapanmasını engellersiniz. Aksi halde **.exe** dosyasını çalıştırır çalıştırmaz program kapanacaktır.
{% endhint %}

## 2. C++ typedef Kullanımı

**`typedef()`** kullanarak mevcut bir tip için yeni bir isim oluşturabilirsiniz.  Aşağıdaki yazım kullanarak yeni bir tür tanımlamak için basit söz dizimi bulunmaktadır.

```cpp
typedef tip yeniad;
```

**Örnek:** int veri türünü artık elma yazarak kullanmak istiyorsak aşağıdaki gibi yeni bir adlandırma oluşturmalıyız.

```cpp
typedef int elma;
elma yas=25;
```

## 3. C++ Enum Tipler (Enum Kullanımı)

Enum bir tür, isteğe bağlı bir tür adı ve türün değerleri olarak kullanılabilecek bir sıfır veya daha fazla tanımlayıcı kümesidir. Her bir sayıcı, türü numaralandırma olan bir sabittir. Her bir enum değeri bir sayı değerine karşılık gelir.

Bir enumerate oluşturmak için **`enum`** anahtar sözcüğünün kullanımını gerektirir. Söz dizimi aşağıdaki gibidir.

```cpp
enum enumadi { degerler } liste-degiskeni;
```

**Örnek:** Her bir gün değeri bir sayı değerine karşılık gelmektedir.0 pazartesi olmak üzere 4 değeri cumaya gelir. ikinci satırda da `gun` değeri carsamba olarak enum’a aktarılmıştır. İsteğe bağlı olarak da enuma istenilen değer verilebilir (cumartesi=8 gibi).

{% tabs %}
{% tab title="C++" %}

```cpp
#include <iostream>

using namespace std;
 
int main() {

    enum gunler{pazartesi,sali,carsamba,persembe,cuma,cumartesi,pazar} gun;
    gun = carsamba;

    cout << "Haftanin " << gun << ". gunundesiniz." << endl;
    
    system("PAUSE");
    return 0;
}
```

{% endtab %}

{% tab title="Ekran Çıktısı" %}

```
Haftanin 2. gunundesiniz.
```

{% endtab %}
{% endtabs %}

Bu örnekte önemli olan enum içerisinde değişkenlere değer atamadığımız için ön tanımlı olarak 0 dan başladı. Bu sebeple ekrana carsamba gününü 2 olarak yazdı. Biz bunu şu şekilde düzeltebiliriz.

{% tabs %}
{% tab title="C++" %}

```cpp
#include <iostream>

using namespace std;
 
int main() {

    enum gunler{pazartesi=1,sali=2,carsamba=3,persembe=4,cuma=5,cumartesi=6,pazar=7} gun;
    gun = carsamba;

    cout << "Haftanin " << gun << ". gunundesiniz." << endl;
    
    system("PAUSE");
    return 0;
}
```

{% endtab %}

{% tab title="Ekran Çıktısı" %}

```
Haftanin 3. gunundesiniz.
```

{% endtab %}
{% endtabs %}

{% hint style="info" %}
İleride yazacağınız büyük programlarda koşul durumlarınız için kontrol değişkenlerini enum ile oluşturarak daha rahat bir programlama yapabilirsiniz. Örneğin `if(x==1)` gibi bir ifade kullanarak bu 1 in neye karşılık geldiğini hatırlamak yerine, `if(x==dogru)` ifadesini kullanarak daha okunaklı program yazmış olursunuz.
{% endhint %}

#### **Enum kullanırken bilinmesi gerekenler:**

* Enum içerisinde değer vermezsek, değerler 0’dan başlar ve birer birer artar.
* Enum’ların varsayılan değer “int”dir.
* Enumları; byte,sbyte, short,ushort, int, uint,long, ulong türlerin oluşturabiliriz.
* Enum içerisine verdiğimiz değerlerde, değişken isimlendirmede dikkat edilen kurallar geçerlidir. Örneğin sayı ile başlayan veya içerisinde boşluk bulunan isimlendirmeler veremeyiz.


# # C++ Değişkenler

C++ Değişkenler (Variables) konusunu işliyoruz.

Değişkenler, programlarımızdaki verilerin tutulduğu adlandırılmış bellek alanlarıdır.  C++’daki her değişken, değişkenin belleğinin boyutunu ve düzenini belirleyen özel bir türe sahiptir. Aşağıdaki ifadeleri sağlayacak şekilde tanımlaması yapılabilir.

Bir değişkenin adı harfler(ANSI standartlarında) , rakamlar ve alt çizgi karakterinden oluşabilir.

Bir harf veya alt çizgi ile başlamalıdır. Büyük ve küçük harfler farklıdır, çünkü C++ büyük / küçük harfe duyarlıdır.

C++ program deyimleri deyimleri dışındaki ifadeler değişken ismi olarak kullanılabilir.(Örn **int** değişken adı olarak kullanılmaz)

Önceki [C++ Syntax](https://derslik.kerteriz.net/c++/c++-syntax) dersinde bu veri türlerinden bahsetmiştik. Aşağıdaki veri tanımlayıcıları ile değişken tanımlaması yapılır.

| Sıra | Tip ve Tanımı                           | Tanımı                                  |
| ---- | --------------------------------------- | --------------------------------------- |
| 1    | <p><strong>bool</strong></p><p></p>     | true /false boolean değer alır.         |
| 2    | <p><strong>char</strong></p><p></p>     | Bir bytelık veri alan tam sayı türüdür. |
| 3    | <p><strong>int</strong></p><p></p>      | Doğal tam sayı veri türüdür.            |
| 4    | <p><strong>float</strong></p><p></p>    | Ondalıklı sayı türü.                    |
| 5    | <p><strong>double</strong></p><p></p>   | Daha geniş ondalıklı sayı türü.         |
| 6    | <p><strong>void</strong></p><p></p>     | Dönüş olmadığını temsil eder.           |
| 7    | <p><strong>wchar\_t</strong></p><p></p> | Geniş bir karakter türü.                |

C++ ayrıca `Enumeration`, `Pointer`, `Array`, `Reference`, `Data structure`, ve `Class`türlerini tanımlamaya da izin verir.

Aşağıdaki işlemler bir değişken nasıl tanımlanıp kullanılacağını kapsamaktadır.

## 1. C++ Değişken Tanımlama

Bir değişken tanımlaması derleyiciye değişken için ne kadar alan oluşturulacağını söyler. Bir değişken tanımlaması değişken tipi, değişken adı  ve  varsa eşittir(=) ile değişkenin aldığı değer olacak şekilde tanımlanır.

```
tip degisken_listesi;
tip degisken_adi = deger;
```

Örnek olarak:

```cpp
int yas;
string isim = "Ali";
int    a, b, c = 10;
char   cins, karakter;
float  sicaklik, maas;
double degisken;
```

## 2. **Değişkene Değer Verme Çeşitleri**

Direkt değer verme daha iyi performans gösterebilir. Ayrıca birkaç güçlü yana sahiptir. Bunun dışında `direct initialization` sayesinde atama ve ilk değer verme işlemlerini birbirinden daha rahat ayırabiliriz.

```cpp
int x = 5 // Copy initialization

int  y(10); // Direct initialization

int z{5}; // Uniform initialization (C++11)
```

`Uniform initialization` bir takım sebeplerden dolayı diğer iki tanımlamadan daha iyidir. Diğer iki tanımlama türüyle veri listeleri tanımlanamaz. Boş bir süslü parantez ile tanımlanan veri otomatik olarak sıfır değerini alır.

```cpp
int a{6}; //Calisir

int b{};  //Calisir, sifir degeri alir.

int c{5.5} // Derleyici hata atar. integer degisken double deger alamaz.
```

İlk olarak bir değişken oluşturarak ardından bu boş değişkene değer atayabilirsiniz.

```cpp
bool degisken;

degisken = false; // Kopyalayarak atama
```

C++ dilinde değişkenlere varsayılan olarak değer ataması yapılmaz. Eğer programcı tarafından değer ataması yapılmamışsa değişken ramde saklandığı yerin önceki verisini tutmaya devam eder.

## 3. Çoklu Değişken Tanımlama

Tek satırda birden çok değişken oluşturabilirsiniz. Bu sayede daha az satırla daha hızlı tanımlamalar yapabilirsiniz.

```cpp
int a,b,c; // Uygun


/*  Uygun  */
int a;
int b;
int c;

int a(5), b{4}, c = 0; Uygun

int a, int b; // derleme hatası
```

## 4. Yerel Değişkenler

Bir fonksiyon veya blok içinde bildirilen değişkenlerdir. Sadece bu fonksiyon yada blok içinde kullanılabilirler. Yerel değişkenler kendi fonksiyonları dışında çalışmamaktadırlar. Aşağıdaki kullanım örneğini inceleyin.

```cpp
#include <iostream>
using namespace std;
 
int main () {
   // main fonksiyonu icinde tanimlanan yerel degisken
   int a, b, c;
 
   // deger atamasi
   a = 10;
   b = 20;
   c = a + b;
 
   cout << c;
 
   return 0;
}
```

## 5. Global Değişkenler

Global değişkenler, genellikle programın üstünde yer alan tüm fonksiyonların dışında tanımlanır. Global değişkenler, programınızın ömrü boyunca değerlerini koruyacaktır.

Global bir değişkene herhangi bir fonksiyon erişilebilir. Yani, global bir değişken, bildiriminin tamamlanmasından sonra tüm programınızda kullanılabilir. Aşağıda, global ve yerel değişkenleri kullanan örnek verilmiştir.

```cpp
#include <iostream>
using namespace std;
 
// Global tanimlama
int g;
 
int main () {
   // Local tanimlama
   int a, b;
 
   // deger atama
   a = 10;
   b = 20;
   g = a + b;
  
   cout << g;
 
   return 0;
}
```

{% hint style="info" %}
**Dikkat:** Bir program yerel ve global değişkenlere aynı anda sahip olabilir, ancak bir fonksiyon içindeki yerel değişkenin değeri tercih edilir.
{% endhint %}

```cpp
#include <iostream>
using namespace std;
 
// global
int g = 20;
 
int main () {
   // local
   int g = 10;
 
   cout << g; //cikti 10 olacaktir
 
   return 0;
}
```

{% hint style="info" %}
&#x20;**Dikkat:** Yerel bir değişken tanımlandığında, sistem tarafından otomatik başlatılmaz, bunu kendiniz başlatmanız gerekir.  Global değişkenler tanımlandığında, sistem tarafından otomatik olarak ilk değer ataması yapar. (İlk değer ataması yapılmadığında oluşacak durum)
{% endhint %}

| Veri Tipi | Başlangıç değeri |
| --------- | ---------------- |
| int       | 0                |
| char      | ‘\0’             |
| float     | 0                |
| double    | 0                |
| pointer   | NULL             |

## **6. Statik Değişkenler**

Program işlediği sürece bellekte kendisine belirli bir yer ayrılan değişken türüdür. Program çalışma süresince sadece bir kere tanımlanır. Örneğin bir fonksiyon içerisindeki bir statik değişken fonksiyon ne kadar çağrılırsa çağrılsın bir kez tanımlanır.

{% tabs %}
{% tab title="C++" %}

```cpp
#include <iostream>

void ArttirVeYazdir()
{
    static int s_deger = 1;
    // Degisken statiktir.

    ++s_degisken;
    std::cout << s_degisken << std::endl;

} // s_degisken yok edilmedi.

int main()
{
    ArttirVeYazdir();
    ArttirVeYazdir();
    ArttirVeYazdir();

}
```

{% endtab %}

{% tab title="Program Çıktısı" %}

```
2
3
4
```

{% endtab %}
{% endtabs %}

## 7. Auto Deyimi

`Auto` deyimi eğer değişken tanımlanırken değer alıyorsa kullanılır. Örneğin bir double değişkene 5.5 değerini vereceksek derleyici tanımlayacağımız değişkenin zaten double olduğunu çözebilir. Örneğin:

```cpp
double x{ 5.6 };  //Derleyici 5.6'nin double literal oldugunu biliyor.

auto x{ 5.6 }; //Yukaridakiyle ayni is yapilir. Derleyici x'in double oldugunu biliyor.
```

`auto` kullanıldığı zaman, derleyiciye, tanımlanan değişkenin atanacak değerin türü olacağı bildirilir. Bu işlem fonksiyon parametreleri için kullanılmaz. Örneğin:

## 8. C++ extern Değişken Tanımlama

Bir değişken beyanı derleyiciye verilen tip ve isimde bir değişken bulunduğunu ve böylece derleyicinin değişken hakkında tam bir ayrıntıya ihtiyaç duymadan daha fazla derleme için ilerlediğini garanti eder. Bir derleme bildiriminin yalnızca derleme sırasında anlamı vardır, derleyici programa bağlandığı sırada gerçek değişken tanımına ihtiyaç duyar.

Değişken bildirimi, birden fazla dosya kullandığınızda ve değişkeninizi, programın bağlandığı sırada kullanılabilen dosyalardan birinde tanımladığınızda kullanışlıdır. Herhangi bir yerde bir değişken bildirmek için **extern** anahtar sözcüğünü kullanmalısınız. C++ farklı bloklarda bir değişkeni birden çok kez bildirme imkanı sunar, ancak bir dosyada, bir işlevde veya bir kod bloğunda yalnızca bir kez tanımlanabilir.

```cpp
#include <iostream>
using namespace std;
 
// Degisken tanimlama
extern int a, b;
extern float f;
 
int main () {

    int a, b;
    float f;
    
    // deger atama
    a = 10;
    b = 20;
 
    cout << "toplam :" << a + b << endl ;
 
    f = 50.0/3.0;
    cout << "ondalik :" << f << endl ;
    
    system("PAUSE");
    return 0;
}
```

Aynı kavram, function beyanı sırasında da yapılır. Function beyanı önce yapılıp, fonksiyon her hangi bir yerde tanımlanabilir. Aşağıdaki örnek bu kavramı açıklamaktadır.

```cpp
#include <iostream>
using namespace std;
 
// function beyani
int ornek();
int main() {
    
   // function cagirma
   int i = ornek();
}
 
// function tanımlama
int ornek() {
   return 125;
}
```


# # C++ Değişmezler

C++ Değişmezler (Literals) konusunu işliyoruz.

C++ programlama dilinde temel veri türlerinin değiştirilemez sabitleri vardır. Bu sabitler literal olarak isimlendirilir.  Sabitler **Integer** , **Float**, **Char**, **String** ve **Boolean** veri türlerinden oluşabilir. Bu sabitlerin yazım kuralı dışında kullanımları değişkenler gibidir.

## 1. Tam Sayı Değişmezleri (Integer Literals)

Tam sayı türünün, ifadelerde doğrudan kullanılmasına izin verir. Bir tamsayı değişmezi, ondalık (decimal), sekizlik(octal) , onaltılık(hexadecimal ) veya ikilik (binary) bir sabit olabilir. Daha fazla bilgi için [Cppreferences  integer literal](https://en.cppreference.com/w/cpp/language/integer_literal) bakabilirsiniz.

* **Onluk değişmez (decimal literal) :** Başıdan sıfır (0) olmayan onluk basamak değerlerine sahip bir sayıyı ifade eder.
* **Sekizlik değişmez (octal literal) :** Başındaki sıfırı takip eden sıfır yada daha fazla basamağı ifade eder. (Basamak rakamları 0,1,2,3,4,5,6,7 olabilir)
* **Onaltılık değişmez (hex literal) :** 0x yada 0X ile başlayan ve içirisinde 0,1,2,3,4,5,6,7,8,9,a,A,b,B,c,C,d,D,e,E,f,F rakamlarını içeren onaltılık sayıları ifade eder.
* **İkilik değişmez (binary literal) :** 0b yada 0B ile başlayan ve içinde sadece 0,1 rakamlarını içeren sayıları ifade eder.

```cpp
int d = 42;
int o = 052;
int x = 0x2a;
int X = 0X2A;
int b = 0b101010; // C++14
```

### 1.1 Değişmezler için İzin Verilen Kelimeler

|                            |                                                                             |                                                                                                                              |
| -------------------------- | --------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------- |
| suffix                     | decimal bases                                                               | binary, octal, or hexadecimal bases                                                                                          |
| no suffix                  | <p>intlong int<br>long long int(since C++11)</p>                            | <p>intunsigned int<br>long int<br>unsigned long int<br>long long int(since C++11)<br>unsigned long long int(since C++11)</p> |
| `u` or `U`                 | <p>unsigned intunsigned long int<br>unsigned long long int(since C++11)</p> | <p>unsigned intunsigned long int<br>unsigned long long int(since C++11)</p>                                                  |
| `l` or `L`                 | <p>long intunsigned long int(until C++11)<br>long long int(since C++11)</p> | <p>long intunsigned long int<br>long long int(since C++11)<br>unsigned long long int(since C++11)</p>                        |
| both `l`/`L` and `u`/`U`   | unsigned long intunsigned long long int(since C++11)                        | unsigned long int(since C++11)unsigned long long int(since C++11)                                                            |
| `ll` or `LL`               | long long int(since C++11)                                                  | long long int(since C++11)unsigned long long int(since C++11)                                                                |
| both `ll`/`LL` and `u`/`U` | unsigned long long int(since C++11)                                         | unsigned long long int(since C++11)                                                                                          |

Yukarıdaki tablo **cppreference.com** adresinden alınmıştır.

Yukarıdaki tabloya göre aşağıdaki şekilde tanımlamalar yapılabilir.

```cpp
int a= 212;       
<span class="t-c"><span class="mw-geshi cpp source-cpp"><span class="kw4">unsigned</span> <span class="kw4">long</span> <span class="kw4">int  b = </span></span></span>215u;     
<span class="t-c"><span class="mw-geshi cpp source-cpp"><span class="kw4">long</span> <span class="kw4">int c = </span></span></span>0xFeeL;
```

```cpp
85         // decimal
0213       // octal
0x4b       // hexadecimal
30         // int
30u        // unsigned int
30l        // long
30ul       // unsigned long
```

## 2. Ondalıklı Sayı Değişmezler (Floating Point Literals)

Kayan nokta değişmez değeri, kaynak dosyada değeri belirtilen bir derleme zamanı sabiti tanımlar. Daha fazla bilgi için[ https://en.cppreference.com/w/cpp/language/floating\_literal](https://en.cppreference.com/w/cpp/language/floating_literal)

Ondalık formunu kullanarak temsil ederken, ondalık noktayı, üssü veya her ikisini de içermeli ve üstel form kullanarak temsil ederken, tamsayı kısmını, kesirli parçayı veya her ikisini de içermelidir. İmzalı üs, e veya E tarafından tanıtılmaktadır.

```cpp
3.14159     
314159E-5L
```

```cpp
#include <iostream>
int main()
{
  std::cout << 58.         << '\n'
            << 4e2         << '\n'
            << 123.456e-67 << '\n'
            << .1E4f       << '\n'
            << 0x10.1p0    << '\n';
}
```

## 3. Boolean Değişmezler (Boolean Literals)

Boolean değişmezleri **true** ve **false** anahtar kelimelerdir.

```cpp
bool askerlik =false;
```

## 4. Karakter Değişmezleri (Character Literals)

Karakter değişmezleri tek tırnak içine alınır.  Eğer literal L ile başlarsa (sadece büyük harf), geniş bir karakter literaldir (örn., L’e ‘)  ve wchar\_t değişken tipinde saklanmalıdır. Aksi halde, dar bir karakter değişmezidir (örneğin, ‘e’) ve basit bir char tipi değişkeni içinde saklanabilir.

Bir karakter değişmezi, düz bir karakter olabileceği gibi bir kaçış karakteri yada evrensel bir karakter olabilir.

```cpp
'x'       //normal bir karakter
'\t'      //kaçış karakteri
'\u02C0'  //evrensel bir karakter
```

Tüm kaçış karakteri listesi aşağıda verilmiştir.

| Escape sequence | Meaning                  |
| --------------- | ------------------------ |
| \\\\            | \ (slash) karakteri      |
| \’              | ‘ tırnak karakteri       |
| \”              | ” çift tırnak karakteri  |
| \\?             | ? soru işareti karakteri |
| \a              | Uyarı yada  Alarm        |
| \b              | Backspace                |
| \f              | Sayfa başı               |
| \n              | Yeni satır               |
| \r              | Satır başı               |
| \t              | Yatay tab                |
| \v              | Dikey tab                |

```cpp
#include <iostream>
using namespace std;
 
int main() {
   cout << "Merhaba\tDunya\n\n";
   return 0;
}
```

## 5. String Literals

Dize değişmezleri çift tırnak içine alınır. Bir dize, karakter değişmezlerine benzer karakterler içerir: düz karakterler, çıkış sıraları ve evrensel karakterler. Ayrıca L, u8, U, u öneklerini alabilir. Öneklerin kullanımı ile ilgili [detay için tıklayın.](https://en.cppreference.com/w/cpp/language/string_literal)

{% hint style="info" %}
**Null** değer atamak istenirse **‘\0’** ataması yapılmalıdır.
{% endhint %}


# # C++ Sabitler

C++ Sabitler konusunu işliyoruz.

Sabitler, programda belirli bir değere sahip değişkenlerdir. Program boyunca bu değeri hafızasında tutacak ve hep kullanacaktır. Bu sebeple yazıldıkları yer bakımından da işlev bakımından da değişkenlerden biraz farklıdırlar.

* Sabitler, normal değişkenler gibidir. Ama bir kez değer atandıktan sonra program tarafından değiştirilemez.
* Sabit değerlerde kullanılır. Bu sayede değiştirilmesine izin verilmez. Örneğin Pi sayısı.
* Sabit değerlerin veri tipleri kısıtlaması yoktur. Her veri tipindeki değerleri sabit olarak tanımlayabilirsiniz.

C++ ile sabit tanımlamanın iki yolu vardır.

* **#define** kullanarak.
* **const** anahtar kelimesini kullanarak.

## 1. define Tanımlayıcı Değer

Programınızın başında sabit değer alacak değişkenleri `define` anahtar kelimesi ile tanımlayarak program içinde daha anlaşılabilir bir şekilde kullanabilirsiniz. Sabit değerde değişiklik yapacağınız zaman `define` ile oluşturduğunuz değeri güncellemeniz yeterli olacaktır.

```cpp
#include <iostream>
using namespace std;
 
#define UZUNLUK 10   
#define GENISLIK 5
 
int main() {
   int alan;  
   alan = UZUNLUK * GENISLIK ;
   cout << alan;
   return 0;
}
```

## 2. const Anahtar Kelimesi

Aşağıdaki gibi belirli bir türdeki sabitleri bildirmek için `const` ön ekini kullanabilirsiniz.

```cpp
#include <iostream>
using namespace std;
 
int main() {
   const int  YUKSEKLIK = 10;
   const int  GENISLIK  = 5;
   int alan;  
   
   area = YUKSEKLIK * GENISLIK;
   cout << alan;
   return 0;
}
```

## 3. **#define ve const Arasındaki Fark**

**`define`** methodu bir önişlemci gibi davranır. Yani herhangi bir derleme işlemine girmez ve kodda yeniden aranır. **`Const`** ise gerçek bir değişken gibi davrandığı için tüm işlemler rahatlıkla gerçekleştirilir. Temelde ikisi de aynı işi yapar ve hatta ikisi de birbirinden neredeyse farksızdır diyebiliriz. Lakin hata derleyicileri bir program için oldukça önemlidir ve **`const`** bir değişken olarak davrandığından dolayı bu alanda size avantaj sağlayacaktır. Bunun dışında basit işlemlerde olmasa bile kompleks yapılı işlemlerde **`define`** methodunda problemlerin yaşandığı söylenmektedir. Bu sebeple **C++ programlama dilinde tercih edilmesi gerekenin const olduğunu yazılımcılar dile getirmektedir.**


# 🖥️ Nginx

Bu sayfadan Nginx hakkında birçok ders içeriğine ücretsiz ulaşabilirsiniz.


# Nginx Nedir?

Nginx hakkında temel bilgileri bu derste bulabilirsiniz.

**Nginx**, açık kaynak kodlu ve yüksek performanslı bir web sunucu yazılımıdır. İlk olarak *mail.ru* için *Igor Sysoev* tarafından mail sunucusu olarak yazılmıştır. Fakat gösterdiği başarı ile şu işlemler içinde kullanılabilir hale gelmiştir:

* HTTP, TCP ve UDP web sunucusu
* Proxy sunucusu
* Reverse proxy (ters vekil sunucusu)
* Load Balancer (HTTP yük dengeleyicisi)
* Mail sunucusu (IMAP, POP3 ve SMTP)

## 1. Neden Nginx Kullanmalıyım?

Nginx kullanmanız için birçok sebep vardır. Bunları şu şekilde sıralayabiliriz.

* Açık kaynak kodlu ve ücretsizdir.
* Konfigürasyonu ve söz dizimi kolaydır
* Dökümantasyonu geniştir ve rahat erişilebilir
* Minimum bellek kullanımı ister
* Sistem gereksinimleri düşüktür
* Yüksek performans sunar
* Yük dengeleme (load balancing)
* Yerine çalışma (failover)

## 2. Nginx Nasıl Çalışır?

Bir istemci, web sayfasını açmak istediğinde istemcinin tarayıcısı web sayfasının sunucusu ile bağlantı oluşturur yani soket açar. İlgili web sayfasının bulunduğu sunucu da bu sayfayı sunucuda bularak istemciye sunar.  Bu olaya **thread** adı verilmektedir.

**Apache** gibi klasik web sunucu yazılımları  **blocking model** adı verilen bir mimariye sahiptir gelen her istek başına bir thread oluşturur. Buna bağlı olarakta her thread için belirli bir bellek ayırır. Fakat bu çalışma şekli c10k ismi verilen bir probleme yol açar.&#x20;

**Nginx** her istek için bir thread oluşturmak yerine **olay-güdümlü, asenkron bir mimarisi (** **Asynchronous Event-Driven Model)** ile bir ana işlem içinde (main process) asenkron çok sayıda işçi işlemler (*worker process*) kullanmaktadır.

**Nginx** her işçi’ye, verilen görevlerin gerçekleşimi ile ilintili bir event handler bağlar. Görev alan işçi işi tamamladıktan sonra bir event fırlatır ve bu event, kendisine bağlı handler tarafından yakalanarak main processe iletilir. Bu sayede, context switch (*blocking model çalışma prensibi*) gibi bir mekanizmaya ihtiyaç kalmaz ve thread sayısı arttıkça artan bekleme süresi ve buna bağlı sistemin geç yanıt vermesi gibi sorunlar ortadan kalkar.

![Nginx Çalışma Şekli](/files/-Lvb4lcjBHE9J68QQBiz)

{% hint style="info" %}
Her **worker process** bir işlemci gücünü temsil eder. Örneğin 8 çekirdekli bir sunucuda 4 worker process ayarlanırsa, her worker process 2 çekirdek kullanır.
{% endhint %}

{% hint style="info" %}
Her **worker connection** bir thread i temsil eder. Bir worker process 1024 adet worker connection barındırabilir. Nginx in gücü buradan gelir.
{% endhint %}

## 3. Nginx vs Apache Kıyaslaması

Nginx sunucu yazılımının gücünü test edebilmemiz için uzun yıllardır kullanılan Apache sunucu yazılımı ile kıyaslayabiliriz.

![4KB lık bir dosyayla yapılan test](/files/-Lvb8taXJ8cSYVZ8rNGU)

Static bir dosya üzerinde yapılan testte Nginx saniyede 26003 işleme cevap verebilirken Apache 12416 işleme cevap verebilmiştir.

!["Hello World" yazılı PHP dosyasıyla yapılan test](/files/-Lvb9FXcOxgleu4oyOcK)

Bir PHP dosyası sunucuda yorumlanarak istemciye gönderilir. Böylece sunucu ile etkileşime geçmiş olunur. "Hello World" yazılı bir PHP dosyası üzerinde yapılan testte Nginx saniyede 10674 işleme cevap verebilirken Apache 9647 işleme cevap verebilmiştir.

![Wordpress ve Cache kurulu test](/files/-Lvb9l47z5Jku6CxGsXS)

Wordpress oldukça ağır bir PHP uygulamasıdır ve cache eklentileri büyük öneme sahiptir. Cache eklentileriyle birlikte kullanılan Wordpress üzerinde yapılan testte Nginx saniyede 9220 işleme cevap verebilirken Apache 2171 işleme cevap verebilmiştir.

## 4. Nginx Kullanan Siteler

Nginx kullanan 43 milyon siteden ([kaynak](https://news.netcraft.com/archives/2019/07/26/july-2019-web-server-survey.html)) başlıcaları şu şekildedir:

1. duckduckgo.com
2. bitbucket.org
3. vk.com
4. blog.csdn.net
5. gitlab.com
6. xvideos.com
7. ahrefs.com
8. pornhub.com
9. app.asana.com&#x20;
10. news.ycombinator.com

## 4. Özet

Nginx, ücretsiz ve oldukça başarılı bir web sunucu yazılımıdır. Üstelik milyonlarca site tarafından kullanılırken popülerliği de sürekli artmaktadır. Öğrenmesi ve kaynak bulması kolay, sunduğu performansı yüksek ve uygulama alanları geniş olması açısından tercih edebilirsiniz.&#x20;

> Nginx ten daha performanslı web sunucu yazılımları mevcuttur. İlerleyen zamanlarda ilgili web sunucu yazılımının derslerini ekleyeceğiz fakat Nginx ile başlamanız daha uygun olacaktır.


# ⚙️ Nginx Kurulumu

Nginx web sunucu yazılımının nasıl kurulacağını öğreneceğiz.

Nginx web sunucu yazılımının ne olduğunu ve nasıl çalıştığını öğrendikten sonra artık kurulum dersimize başlıyoruz. Bu dersimizde **Ubuntu 16.04** işletim sistemini kullanarak konuları işleyeceğiz.

## 1. İşletim Sisteminin Güncellenmesi

Kuruluma başlamadan önce işletim sistemini güncellememiz fayda sağlayacaktır.&#x20;

```bash
sudo apt update
sudo apt upgrade
```

## 2. Nginx Paketinin Kurulması

Nginx web sunucusunu artık indirerek yükleyebiliriz.

```bash
sudo apt install nginx
```

:pushpin: Herhangi bir sebeple nginx yüklemesini kaldırmak ve tekrar kurmak istediğinizde tüm konfigürasyonu ile birlikte nginx i kaldırmak için şu komutu çalıştırabilir ve ardından yukarıdaki kodla birlikte tekrardan yükleyebilirsiniz.

```bash
sudo apt purge nginx nginx-common nginx-full
```

## 3. Nginx Konfigürasyonunun Ayarlanması

*Hash bucket memory* problemini engellemek için ([Problem Nedir?](https://gist.github.com/muhammadghazali/6c2b8c80d5528e3118613746e0041263)) **`/etc/nginx`** dizini altında yer alan **`nginx.conf`** dosyasını **nano** veya **gedit** gibi editörlerle açarak `server_names_hash_bucket_size 64` satırının başındaki **#** işaretini siliniz.

{% code title="nginx.conf" %}

```bash
.
.
server_names_hash_bucket_size 64;
# server_name_in_redirect off;
.
.
```

{% endcode %}

## 4. PHP-FPM Paketinin Kurulması

Sunucumuzda PHP dosyalarımızın yorumlanabilmesi için PHP-FPM paketimizi kurmalıyız. Bunun için aşağıdaki komutları çalıştırabilirsiniz.

```bash
sudo add-apt-repository ppa:ondrej/php
sudo apt-get install software-properties-common
sudo apt update
sudo apt-get install php7.3-fpm php7.3-cli php7.3-mysql phpunit
```

Paketleri kurduktan sonra **`/etc/php/7.3/fpm/`** dizini altında yer alan **`php.ini`** dosyamızdaki ilgili alanları düzenleyelim.

{% code title="php.ini" %}

```bash
file_uploads = On
allow_url_fopen = On
memory_limit = 256M
cgi.fix_pathinfo = 0
upload_max_filesize = 100M
max_execution_time = 360
date.timezone = Europe/Istanbul
```

{% endcode %}

Düzenlemelerimizin aktif olabilmesi için servisimizi yenileyelim.

```bash
sudo systemctl restart php7.3-fpm
```

Son olarak **`php -v`** komutu ile ekranda php versiyonunu görüyorsanız işlemimiz tamamdır.

## 5. Güvenlik Duvarını Ayarlama

İşletim sistemimizde güvenlik duvarımız etkinse Nginx web sunucusunun engellenmesini önlemek için Nginx i beyaz listeye eklemeliyiz.

Öncelikle güvenlik duvarı ile hangi uygulamaların kullanılabilir olduğunu görelim.

{% tabs %}
{% tab title="Komut" %}

```bash
sudo ufw app list
```

{% endtab %}

{% tab title="Çıktı" %}

```
Available applications:
  Nginx Full
  Nginx HTTP
  Nginx HTTPS
  OpenSSH
```

{% endtab %}
{% endtabs %}

Komutun çıktısında gördüğünüz uygulamalar için güvenlik duvarına kural yazabiliriz. Öyleyse ilk kuralımızı yazalım.

```bash
sudo ufw allow 'Nginx HTTP'
```

HTTP üzerinden yani 80 portundan gelen trafiğe izin vererek Nginx in kısıtlanmadan kullanılmasını sağladık. Şimdi son durum kontrolünü yapalım.

{% tabs %}
{% tab title="Komut" %}

```bash
sudo ufw status
```

{% endtab %}

{% tab title="Çıktı" %}

```
Status: active

To                         Action      From
--                         ------      ----
OpenSSH                    ALLOW       Anywhere                  
Nginx HTTP                 ALLOW       Anywhere                  
OpenSSH (v6)               ALLOW       Anywhere (v6)             
Nginx HTTP (v6)            ALLOW       Anywhere (v6)
```

{% endtab %}
{% endtabs %}

{% hint style="info" %}
Eğer bu komut sonrası **`Status: inactive`** çıktısını görüyorsanız güvenlik duvarınız zaten kapalı demektir. Bu aşamadaki işlemleri yapmanıza gerek yoktur.
{% endhint %}

## 6. Web Sunucu Kontrolü

Nginx web sunucusunu ikinci adımda yüklemiştik. Şimdi web sunucu servisinin durumunu kontrol edelim.

```bash
systemctl status nginx
```

Nginx web sunucu servisinin durumunu kontrol ettiğimizde aktif olduğunu görmemiz gerekiyor.

```bash
nginx.service - A high performance web server and a reverse proxy server
   Loaded: loaded (/lib/systemd/system/nginx.service; enabled; vendor preset: enabled)
   Active: active (running) since Mon 2019-12-09 11:38:13 PST; 49min ago
     Docs: man:nginx(8)
 Main PID: 2369 (nginx)
    Tasks: 2 (limit: 1153)
   CGroup: /system.slice/nginx.service
           ├─2369 nginx: master process /usr/sbin/nginx -g daemon on; master_process on;
           └─2380 nginx: worker process
```

Yukarıda ki çıktıda olduğu gibi **`Active: active (running)`** çıktısını gördüyseniz Nginx web sunucu yazılımı başarıyla çalışıyor demektir. Artık **`http://sunucu_ip_adresi`** veya **`localhost`** veya **`127.0.0.1`** adresleri üzerinden Nginx default sayfasına erişebilir ve aşağıdaki resimde olduğu gibi çıktıyı görebilirsiniz.

![Nginx default sayfası](/files/-LvgH0qLZFlNI_rJZ4_h)

{% hint style="info" %}
Nginx servisi üzerinde başlatma, durdurma, yeniden başlatma, konfigürasyonu yeniden yükleme işlemlerini yapabilmek için **`sudo systemctl xxx nginx`** komutundaki **xxx** yerine **`start`**, **`stop`**, **`restart`** ve **`reload`** terimlerini kullanabilirsiniz.
{% endhint %}

Artık Nginx web sunucumuzu başarıyla çalıştırdıktan sonra ilerleyen derslerimizde web sunucu uygulamalarımızı kurmaya başlayacağız.


# 🗄️ Sunucu Kurulumları

Nginx web sunucu çeşitlerinin nasıl kurulacağını teker teker öğreneceğiz.


# HTTP Sunucusu Kurulumu

Nginx HTTP web sunucusu kurlumunu anlatıyoruz.

Nginx web sunucu yazılımımızı kurarak çalıştığını gördükten sonra artık ilk sunucu türümüz olan HTTP sunucusu kurulumuna geçiş yapıyoruz. Böylece artık sitelerimizi rahatça kurabileceğiz.

## 1. Hosts Dosyasını Ayarlama

Eğer localhost üzerinde çalışacaksanız öncelikle kendinize özel bir çalışma alanı oluşturmalısınız. Bu derste site örnek adresimiz **`demosite.com`** olacağı için *(siz başka bir isimde belirleyebilirsiniz)* **`/etc/`** klasöründeki **`hosts`** dosyasına aşağıdaki satırı eklemeliyiz.

{% code title="hosts" %}

```
127.0.0.1    demosite.com
```

{% endcode %}

Yani son durumda **`hosts`** dosyamızın aşağıdakine benzer şekilde gözükmesi gerekiyor.

{% code title="hosts" %}

```
127.0.0.1       localhost
127.0.1.1       ubuntu
127.0.0.1       demosite.com
```

{% endcode %}

Özetle bilgisayarınızda istediğiniz bir sanal alan adı oluşturarak ders sonunda tarayıcıdan bu adrese girdiğinizde sitenizi görebileceksiniz.

{% hint style="info" %}
Gerçek bir sunucu üzerinde çalışıyorsanız **127.0.0.1** adresi yerine **sunucu ip adresinizi** yazmanız gerekmektedir.
{% endhint %}

Örnek olarak **`x.x.x.x`** ip adresli sunucumuzda `site1.com`, `site2.com` ve `site3.com` web siteleri varsa **hosts** dosyamız şu şekilde olmalıdır.

{% code title="hosts" %}

```bash
x.x.x.x     site1.com
x.x.x.x     site2.com
x.x.x.x     site3.com
```

{% endcode %}

## 2. Site Dosyalarının Yolunu Belirleme

Bir HTTP sunucusu kurduğumuza göre oluşturacağımız sitenin dosyalarını da bir yerde tutmamız gerekiyor. Bunun için genel olarak kullanılan dizin **`/var/www/`** dizinidir. Bu nedenle bizde yeni klasör oluşturma komutuyla dizinimizi oluşturup içine örnek bir PHP dosyası koyalım.

```
sudo mkdir /var/www/demosite.com/
```

Oluşturduğumuz site klasörüne gerekli izinleri verelim.

```
sudo chown -R $USER:$USER /var/www/demosite.com
sudo chmod -R 755 /var/www
```

Şimdi ise site klasörümüzde **index.php** dosyası oluşturalım.&#x20;

```
sudo touch /var/www/demosite.com/index.php
```

Oluşturduğumuz dosyaya ise **`nano`** metin editörü ile örnek içeriğimizi girelim.

```bash
sudo nano /var/www/demosite.com/index.php
```

{% code title="index.php" %}

```php
<?php 

echo "Merhaba, bu ilk sitemiz!";

?>
```

{% endcode %}

{% hint style="info" %}
Klasör ve dosya oluşturma, dosya içeriğini düzenleme gibi işlemleri direkt konsoldan komutlarla yapmak yerine gezgin üzerinden fare kullanarakta yapabilirsiniz. Ama konsola alışmanız için komutlarla yapmanızı tavsiye ederiz.
{% endhint %}

## 3. Sunucu Bloklarının Oluşturulması

Artık sitemizin konfigürasyon dosyasını oluşturarak siteyi aktif etmenin zamanı geldi. Bunun için **`/etc/nginx/sites-available/`** dizininde yer alan ve Nginx kurulumuyla beraber gelen **`default`** konfigürasyon tablomuzu sitemizin adıyla aynı dizin içine kopyalayarak gerekli düzenlemeleri yapabiliriz. Fakat kolaylık olması amacıyla dosyayı kendimiz oluşturarak aşağıdaki komutları direkt bu dosyamızın içine kopyalayabiliriz.

```bash
sudo touch /etc/nginx/sites-available/demosite.com
```

Dosyamızı **`nano`** veya **`gedit`** ile açarak aşağıdaki komutları içine yapıştırınız.

{% code title="demosite.com" %}

```bash
server {    
    listen 80;
    listen [::]:80;

    server_name demosite.com www.demosite.com;
    root /var/www/demosite.com;
    index index.php index.html;
     
    location / {
        try_files $uri $uri/ @rewrites;
    }
     
    location @rewrites {
        rewrite ^ /index.php last;
    }
     
    location ~ \.php {
        fastcgi_index index.php;
        fastcgi_split_path_info ^(.+\.php)(.*)$;
        include /etc/nginx/fastcgi_params;
        fastcgi_pass unix:/var/run/php/php7.3-fpm.sock;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        } 
}
```

{% endcode %}

Burada yer alan **server\_name** ziyaret edilecek olan alan adıdır. Yani bu domaine bir istek geldiğinde yazdığımız server bloku çalışacaktır. **root** ise site dosyalarının yer aldığı dizin konumudur.&#x20;

:exclamation: **location \~ .php** komutu PHP dosyalarının sunucumuzda yorumlanabilmesini sağlar fakat bu özelliği kullanabilmeniz için `php-fpm` paketini kurmanız gerekiyor. İlgili kurulum [Nginx Kurulumu](https://derslik.kerteriz.net/nginx/nginx-kurulumu) sayfasında yer almaktadır.

{% hint style="info" %}
Eğer siteniz PHP dosyası içermiyor ve sadece HTML dosyalarını içeriyorsa **location \~ .php** özelliğini kullanmanıza gerek yoktur. Konfigürasyondan bu alanı silebilirsiniz.
{% endhint %}

:speaker: Konfigürasyon dosyanızda listen satırında **default\_server** tanımlamasını kullanarak gelen isteğin herhangi bir siteye denk gelmemesi durumunda default olarak çalıştırılacak *server bloku* seçilmiş olur. Örneğin `demosite.com` için **default\_server** tanımlamasını kullanırsak sunucuda olmayan bir site isteği gönderildiğinde `demosite.com` kullanıcıya sunulacaktır. Fakat bu tercih edilen bir kullanım değildir :exclamation:

{% code title="demosite.com" %}

```bash
server {    
    listen 80 default_server;
    listen [::]:80 default_server;

    server_name demosite.com www.demosite.com;
    root /var/www/demosite.com;
    index index.php index.html;
     
    location / {
        try_files $uri $uri/ @rewrites;
    }
     
    location @rewrites {
        rewrite ^ /index.php last;
    }
         
}
```

{% endcode %}

## 4. Sunucu Blokunun Etkinleştirilmesi

Sunucu blokumuzu bir üst başlıkta oluşturduk fakat sitemizin aktif olabilmesi için yazdığımız bloku etkinleştirmemiz gerekiyor. Bunun için aşağıdaki komut ile **`sites-available`** dizinindeki konfigürasyon dosyamızı **`sites-enabled`** dizinine kısayol olarak atıyoruz.

```bash
sudo ln -s /etc/nginx/sites-available/demosite.com /etc/nginx/sites-enabled/demosite.com
```

Ardından Nginx servisini yeniden başlatalım.

```bash
sudo systemctl restart nginx
```

Servisimiz ayağa kalktığında herhangi bir yazım hatası var mı kontrol etmek için aşağıdaki komutu çalıştıralım.

{% tabs %}
{% tab title="Komut" %}

```bash
sudo nginx -t
```

{% endtab %}

{% tab title="Çıktı" %}

```
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful
```

{% endtab %}
{% endtabs %}

Çıktıdaki gibi sonuçları görüyorsanız artık herşey tamamdır demektir.

## 5. Sonuç

Adımları sırasıyla kurduktan sonra tarayıcımızdan **hosts** dosyasında ayarladığınız domain adresine tarayıcınızdan gittiğinizde ekranda sitemizi görebilirsiniz. Bu örnekte **localhost** üzerinde çalıştığımız için rastgele belirlediğimiz **demosite.com** adresini açtığımızda aşağıdaki ekranla karşılaşırız.

![İlk site örneği](/files/-Lvvk19__OJJRt4fcifj)

{% hint style="info" %}
Sunucunuzda aynı işlemleri tekrar ederek istediğiniz kadar site oluşturabilirsiniz.
{% endhint %}


