Python: Okunabilirliği ve Gücü Birleştiren Dil
Günümüzün hızla dijitalleşen dünyasında, programlama dilleri teknolojik yeniliklerin temelini oluşturuyor. Bu diller arasında, özellikle son yıllarda popülerliği katlanarak artan Python, okunabilirliği, basitliği ve çok yönlülüğü ile öne çıkıyor. Guido van Rossum tarafından 1990'ların başında geliştirilmeye başlanan Python, yüksek seviyeli, yorumlanan, genel amaçlı ve dinamik tipli bir dil olarak, başlangıç seviyesinden uzman seviyesine kadar geniş bir geliştirici kitlesine hitap ediyor. Temiz ve anlaşılır sözdizimi, onu öğrenmesi en kolay dillerden biri yaparken, devasa standart kütüphanesi ve zengin üçüncü parti paket ekosistemi sayesinde web geliştirmeden veri bilimine, yapay zekadan otomasyona kadar sayısız alanda güçlü çözümler sunuyor.
Python'un bu kadar sevilmesinin temel nedenlerinden biri "Python Felsefesi" veya "Zen of Python" olarak bilinen ilkeler bütünüdür. "Okunabilirlik önemlidir", "Basit, karmaşıktan iyidir", "Karmaşık, iç içe geçmişten iyidir" gibi ilkeler, Python kodunun sadece yazılmasını değil, aynı zamanda okunmasını ve bakımının yapılmasını da kolaylaştırmayı hedefler. Girintileme (indentation) kullanarak kod bloklarını tanımlama zorunluluğu, bu okunabilirliği pekiştiren önemli bir tasarım kararıdır. Dinamik tipleme özelliği, değişkenlerin tipini açıkça belirtme zorunluluğunu ortadan kaldırarak daha hızlı prototipleme imkanı sunar, ancak büyük projelerde dikkatli kullanılmayı gerektirir.
Python'un kullanım alanları oldukça geniştir. Django ve Flask gibi güçlü framework'ler sayesinde modern ve ölçeklenebilir web uygulamaları geliştirmek mümkündür. Veri bilimi ve makine öğrenmesi alanında ise Pandas, NumPy, Scikit-learn, TensorFlow ve PyTorch gibi kütüphanelerle adeta bir standart haline gelmiştir. Sistem yönetimi görevlerini otomatikleştirmek, bilimsel hesaplamalar yapmak, masaüstü uygulamaları oluşturmak (PyQt, Kivy ile) veya oyun geliştirmek (Pygame ile) Python ile yapılabileceklerden sadece birkaçıdır. Bu rehber, Python'un temel sözdiziminden başlayarak veri yapılarına, fonksiyonlara, nesne yönelimli programlamaya, modüllere ve popüler kullanım alanlarına kadar uzanan geniş bir yelpazede bilgi sunarak, bu güçlü ve keyifli dili öğrenme yolculuğunuzda size sağlam bir temel ve yol haritası sağlamayı amaçlamaktadır.
Python Temelleri: İlk Adımlar
Python dünyasına giriş yapmak için dilin temel kurallarını, kurulumunu ve basit işlemleri nasıl yapacağınızı öğrenmekle başlayabiliriz.
Kurulum ve Ortam Hazırlığı
Python kullanmaya başlamak için bilgisayarınızda yüklü olması gerekir.
- Python İndirme: Resmi Python web sitesi (python.org) üzerinden işletim sisteminize uygun (Windows, macOS, Linux) en son kararlı sürümü indirebilirsiniz. Kurulum sırasında "Add Python to PATH" (Python'ı PATH'e ekle) seçeneğini işaretlemek, komut satırından Python'a kolayca erişmenizi sağlar.
- Kurulumu Doğrulama: Komut istemcisini (Terminal veya Command Prompt) açıp
python --version
veya python3 --version
komutunu çalıştırarak Python'un başarıyla kurulup kurulmadığını ve sürümünü kontrol edebilirsiniz.
- Pip (Paket Yöneticisi): Python ile birlikte gelen standart paket yöneticisidir. Üçüncü parti kütüphaneleri (paketleri) indirmek ve kurmak için kullanılır (örn:
pip install requests
). pip --version
ile kontrol edilebilir ve pip install --upgrade pip
ile güncellenebilir.
- Sanal Ortamlar (Virtual Environments -
venv
): Farklı projelerin farklı kütüphane bağımlılıklarına sahip olması yaygındır. Bu bağımlılıkların birbirine karışmasını önlemek ve proje bazında izole ortamlar oluşturmak için sanal ortamlar kullanılır. Python 3 ile birlikte gelen venv
modülü bunun için standart bir yoldur.
- Ortam Oluşturma: Proje klasörünüzde
python -m venv env_adi
(örn: python -m venv .venv
) komutuyla bir sanal ortam oluşturulur.
- Aktifleştirme:
- Windows (cmd.exe):
.\env_adi\Scripts\activate.bat
- Windows (PowerShell):
.\env_adi\Scripts\Activate.ps1
(ExecutionPolicy ayarı gerekebilir)
- macOS/Linux (bash/zsh):
source env_adi/bin/activate
Aktifleştirildiğinde, komut satırı başında genellikle (env_adi)
ifadesi görünür ve bu ortama kurulan paketler sadece bu proje için geçerli olur.
- Devre Dışı Bırakma:
deactivate
komutu kullanılır.
Her yeni Python projesine bir sanal ortamla başlamak iyi bir pratiktir.
Temel Sözdizimi, "Merhaba Dünya" ve Yorumlar
Python'un sözdizimi okunabilirliğe odaklanır. En önemli özelliklerinden biri, kod bloklarını (if, for, fonksiyon gövdeleri vb.) tanımlamak için süslü parantezler yerine girintileme (indentation) kullanmasıdır. Genellikle 4 boşluk kullanılır ve tutarlılık çok önemlidir.
Klasik "Merhaba Dünya" örneği:
print("Merhaba Dünya!")
Bu kadar basit! print()
fonksiyonu, verilen değeri konsola yazdırır.
Yorumlar: Tek satır yorumları diyez (#
) işareti ile başlar ve satır sonuna kadar devam eder. Python'da C# veya Java'daki gibi çok satırlı yorum bloğu (/* ... */
) yoktur, ancak çok satırlı string literalleri (üç tırnak ile """ ... """
veya ''' ... '''
) bazen bu amaçla kullanılsa da, asıl amaçları docstring oluşturmaktır.
# Bu tek satırlık bir yorumdur.
print("Bu kod çalışacak") # Bu da satır sonu yorumu
"""
Bu çok satırlı bir string literalidir.
Genellikle fonksiyon veya sınıf başında açıklama (docstring)
olarak kullanılır, ancak bazen yorum bloğu gibi de
kullanıldığı görülebilir.
"""
print("Yorumlardan sonra")
Değişkenler ve Atama (Dinamik Tipleme)
Değişkenler, değerleri saklamak için kullanılan isimlendirilmiş yer tutuculardır. Python'da değişken tanımlarken tür belirtmeye gerek yoktur (dinamik tipleme). Değişkenin tipi, ona atanan değere göre otomatik olarak belirlenir.
Atama işlemi =
operatörü ile yapılır.
mesaj = "Merhaba Python" # mesaj değişkeni şimdi bir string
sayi = 10 # sayi değişkeni şimdi bir integer
pi_degeri = 3.14 # pi_degeri şimdi bir float
aktif_mi = True # aktif_mi değişkeni şimdi bir boolean
print(mesaj)
print(sayi)
# Değişkenin tipi sonradan değiştirilebilir (dikkatli kullanılmalı!)
sayi = "Artık metin"
print(sayi)
# Aynı anda birden fazla değişkene atama
x, y, z = 1, "iki", False
print(x, y, z)
# Değişken isimlendirme kuralları:
# - Harf veya alt çizgi (_) ile başlamalıdır.
# - Harf, sayı veya alt çizgi içerebilir.
# - Büyük/küçük harfe duyarlıdır (yas ile Yas farklıdır).
# - Python anahtar kelimeleri (if, for, while, class vb.) kullanılamaz.
# - Okunabilirlik için genellikle küçük harf ve kelimeler arası alt çizgi (snake_case) kullanılır.
kullanici_adi = "testuser"
ilk_sayi = 5
Dinamik tipleme esneklik sağlasa da, değişkenin hangi türde veri tuttuğunu takip etmek önemlidir.
Temel Veri Tipleri
Python'da yerleşik olarak bulunan temel veri tipleri şunlardır:
int
(Integer): Tam sayıları temsil eder (pozitif, negatif veya sıfır). Boyut sınırı pratikte yoktur (bellek yettiği sürece).
yas = 30; sicaklik = -5; sayac = 0
float
(Floating Point Number): Ondalıklı sayıları temsil eder.
pi = 3.14; fiyat = 99.99; oran = 0.5
bool
(Boolean): Mantıksal değerleri temsil eder: True
veya False
(Baş harfleri büyük!).
giris_yapildi = True; hata_var = False
str
(String): Metin dizilerini temsil eder. Tek (' '
), çift (" "
) veya üç tırnak (''' '''
veya """ """
- çok satırlı stringler için) içine alınır. String'ler değiştirilemez (immutable).
isim = "Abdulkadir"
mesaj = 'Python öğreniyorum.'
siir = """
Bu bir
çok satırlı
şiirdir.
"""
NoneType
: Özel bir tiptir ve sadece tek bir değere sahiptir: None
. Bir değerin olmadığını veya boş olduğunu belirtmek için kullanılır (diğer dillerdeki null
'a benzer).
sonuc = None
Bir değişkenin tipini öğrenmek için type()
fonksiyonu kullanılabilir:
print(type(isim)) # <class 'str'>
print(type(yas)) # <class 'int'>
print(type(pi)) # <class 'float'>
print(type(aktif_mi)) # <class 'bool'>
print(type(sonuc)) # <class 'NoneType'>
Tip Dönüşümleri
Farklı veri tipleri arasında dönüşüm yapmak için yerleşik fonksiyonlar kullanılır:
int(deger)
: String veya float'ı integer'a çevirir (float'ın ondalık kısmı atılır).
float(deger)
: String veya integer'ı float'a çevirir.
str(deger)
: Herhangi bir tipi string'e çevirir.
bool(deger)
: Bir değeri boolean karşılığına çevirir. Genellikle 0
, None
, boş string (""
), boş liste ([]
), boş sözlük ({}
) vb. False
; diğer değerler True
olur.
sayi_str = "123"
sayi_int = int(sayi_str)
print(sayi_int + 5) # 128
ondalik_str = "99.5"
ondalik_float = float(ondalik_str)
print(ondalik_float / 2) # 49.75
rakam = 42
rakam_str = str(rakam)
print("Rakam: " + rakam_str) # "Rakam: 42"
print(bool(0)) # False
print(bool(10)) # True
print(bool("")) # False
print(bool("abc"))# True
print(bool(None)) # False
print(bool([])) # False
Dönüşüm her zaman mümkün olmayabilir (örn: int("abc")
ValueError verir).
Operatörler
Değerler üzerinde işlem yapmak için kullanılır:
- Aritmetik Operatörler:
+
, -
, *
, /
(gerçek bölme - sonuç float), //
(tam sayı bölmesi - taban bölme), %
(modülüs - kalan), **
(üs alma).
- Atama Operatörleri:
=
, +=
, -=
, *=
, /=
, //=
, %=
, **=
.
- Karşılaştırma Operatörleri:
==
(eşit), !=
(eşit değil), <
, >
, <=
, >=
. Sonuç True
veya False
döner.
- Mantıksal Operatörler:
and
(VE), or
(VEYA), not
(DEĞİL). Boolean değerler üzerinde çalışır.
- Üyelik Operatörleri: Bir değerin bir dizi, liste, tuple, set veya string gibi bir koleksiyon içinde olup olmadığını kontrol eder.
in
: Eleman koleksiyonda varsa True
döner.
not in
: Eleman koleksiyonda yoksa True
döner.
- Kimlik Operatörleri: İki değişkenin bellekteki aynı nesneyi işaret edip etmediğini kontrol eder.
is
: İki değişken aynı nesneyse True
döner.
is not
: İki değişken farklı nesnelerse True
döner.
- Not:
==
değer eşitliğini kontrol ederken, is
kimlik (bellek adresi) eşitliğini kontrol eder. Küçük sayılar ve string'ler için Python optimizasyon yapabilir ve is
bazen beklenmedik şekilde True
dönebilir, ancak genel olarak nesne kimliği için kullanılır.
# Aritmetik
print(10 / 3) # 3.333...
print(10 // 3) # 3
print(10 % 3) # 1
print(2 ** 4) # 16
# Karşılaştırma
print(5 == 5.0) # True (değerler eşit)
print(5 != '5') # True (tipler farklı)
# Mantıksal
x = 10
print(x > 5 and x < 20) # True and True => True
print(x < 0 or x == 10) # False or True => True
print(not (x == 10)) # not True => False
# Üyelik
liste = [1, 2, 3, 4]
print(3 in liste) # True
print(5 not in liste) # True
print('a' in 'banana') # True
# Kimlik
a = [1, 2]
b = [1, 2]
c = a
print(a == b) # True (içerikleri aynı)
print(a is b) # False (bellekte farklı nesneler)
print(a is c) # True (aynı nesneyi işaret ediyorlar)
Girdi ve Çıktı (input()
, print()
, f-string)
input(prompt)
: Kullanıcıdan veri almak için kullanılır. prompt
(isteğe bağlı) kullanıcıya gösterilecek mesajdır. Kullanıcının girdiği değer her zaman string olarak döndürülür. Sayısal işlem yapılacaksa tip dönüşümü (int()
, float()
) gereklidir.
print(*objects, sep=' ', end='\n', file=sys.stdout, flush=False)
: Değerleri konsola veya belirtilen dosyaya yazdırır.
*objects
: Yazdırılacak bir veya daha fazla değer (virgülle ayrılır).
sep
: Değerler arasına konulacak ayırıcı (varsayılanı boşluk).
end
: Yazdırma işlemi sonuna eklenecek karakter (varsayılanı yeni satır \n
).
file
: Yazdırılacak yer (varsayılanı standart çıktı - konsol).
flush
: Çıktı tamponunun hemen boşaltılıp boşaltılmayacağı.
- f-string (Formatted String Literals - Python 3.6+): String içine değişken veya ifadeleri kolayca yerleştirmenin modern ve okunabilir yoludur. String'in başına
f
veya F
harfi konur ve değişkenler/ifadeler süslü parantez {}
içine yazılır. Biçimlendirme seçenekleri de eklenebilir.
# Kullanıcıdan girdi alma
isim = input("Adınızı girin: ")
yas_str = input("Yaşınızı girin: ")
# Tip dönüşümü
try:
yas = int(yas_str)
except ValueError:
yas = 0
print("Geçersiz yaş girdiniz!")
# Çıktı yazdırma
print("Merhaba", isim, "! Yaşınız:", yas) # Virgülle ayırarak (aralara boşluk koyar)
print("Merhaba " + isim + "! Yaşınız: " + str(yas)) # String birleştirme ile
# f-string kullanımı (Önerilen)
print(f"Merhaba {isim}! Gelecek yıl {yas + 1} yaşında olacaksınız.")
# f-string ile biçimlendirme
fiyat = 123.4567
print(f"Ürün Fiyatı: {fiyat:.2f} TL") # Ondalık kısmı 2 basamakla sınırla
# print parametreleri
print("Elma", "Armut", "Muz", sep=", ", end=".\n") # Çıktı: Elma, Armut, Muz.
Kontrol Yapıları: Program Akışını Yönetme
Kontrol yapıları, kodun hangi koşullarda veya kaç kez çalışacağını belirleyerek programın akışını yönlendirir.
Koşullu İfadeler (if
, elif
, else
)
Belirli bir koşulun doğru olup olmadığını kontrol eder ve buna göre farklı kod bloklarını çalıştırır.
if
: Koşul doğruysa (True
ise) altındaki girintili blok çalışır.
elif
(else if): Önceki if
veya elif
koşulları yanlışsa ve kendi koşulu doğruysa çalışır. Birden fazla elif
olabilir.
else
: Yukarıdaki hiçbir if
veya elif
koşulu doğru değilse çalışır. İsteğe bağlıdır ve en sonda yer alır.
Koşullar genellikle karşılaştırma ve mantıksal operatörler kullanılarak oluşturulur.
puan = int(input("Notunuzu girin (0-100): "))
if puan >= 90 and puan <= 100:
harf_notu = "A"
print("Harika!")
elif puan >= 80:
harf_notu = "B"
elif puan >= 70:
harf_notu = "C"
elif puan >= 60:
harf_notu = "D"
elif puan >= 0:
harf_notu = "F"
print("Daha çok çalışmalısın.")
else:
harf_notu = "Geçersiz"
print("Lütfen 0-100 arası bir değer girin.")
if harf_notu != "Geçersiz":
print(f"Harf notunuz: {harf_notu}")
# Tek satır if (Ternary benzeri ama tam değil)
durum = "Geçti" if puan >= 60 else "Kaldı"
if harf_notu != "Geçersiz":
print(f"Durum: {durum}")
Unutmayın, Python'da bloklar girintileme ile belirlenir.
Döngüler (for
, while
)
Belirli kod bloklarını tekrar tekrar çalıştırmak için kullanılır.
for
Döngüsü: Bir koleksiyon (liste, tuple, string, set, dictionary keys/values/items) veya yinelenebilir (iterable) başka bir nesne üzerindeki her bir eleman için döner.
range(start, stop, step)
Fonksiyonu: Belirli bir aralıkta sayılar üretmek için sıkça for
ile kullanılır. start
dahil, stop
hariçtir. start
verilmezse 0'dan başlar, step
verilmezse 1 artar.
meyveler = ["elma", "armut", "muz"]
print("Meyveler:")
for meyve in meyveler:
print(f"- {meyve}")
print("\nSayılar (0-4):")
for i in range(5): # 0, 1, 2, 3, 4
print(i, end=" ") # 0 1 2 3 4 .
print()
print("\nSayılar (2-8, 2şer):")
for i in range(2, 9, 2): # 2, 4, 6, 8
print(i, end=" ") # 2 4 6 8 .
print()
metin = "Python"
for harf in metin:
print(harf)
# Sözlük üzerinde döngü
urun_fiyatlari = {"kalem": 5, "defter": 15, "silgi": 3}
print("\nÜrünler:")
for urun in urun_fiyatlari: # Sadece anahtarlar üzerinde döner
print(urun)
print("\nÜrün ve Fiyatlar:")
for urun, fiyat in urun_fiyatlari.items(): # items() ile anahtar ve değer alınır
print(f"{urun}: {fiyat} TL")
while
Döngüsü: Belirtilen koşul True
olduğu sürece dönmeye devam eder. Koşulun döngü içinde bir noktada False
olacak şekilde güncellenmesi gerekir, aksi takdirde sonsuz döngü oluşabilir.
sayac = 0
while sayac < 5:
print(f"While sayaç: {sayac}")
sayac += 1 # Koşulu değiştiren güncelleme
print("While döngüsü bitti.")
# Kullanıcı belirli bir girdi yapana kadar dönme
# sifre = ""
# while sifre != "12345":
# sifre = input("Şifreyi girin: ")
# print("Şifre doğru!")
Döngü Kontrol İfadeleri (break
, continue
, pass
)
break
: İçinde bulunduğu en yakın döngüyü (for
veya while
) hemen sonlandırır. Döngünün geri kalan adımları ve varsa else
bloğu çalıştırılmaz.
continue
: Döngünün mevcut adımını atlar ve bir sonraki adıma geçer. Döngü sonlanmaz.
pass
: Hiçbir şey yapmayan bir ifadedir. Sözdizimsel olarak bir blok gerektiği (örn: if
, for
, fonksiyon tanımı) ancak mantıksal olarak hiçbir işlem yapılmayacağı durumlarda yer tutucu olarak kullanılır.
- Döngülerle
else
Bloğu: Python'da for
ve while
döngülerinden sonra bir else
bloğu kullanılabilir. Bu blok, döngü normal bir şekilde tamamlanırsa (yani bir break
ifadesi ile çıkılmazsa) çalıştırılır.
print("Break Örneği:")
for i in range(10):
if i == 5:
print("5 bulundu, döngüden çıkılıyor.")
break # Döngüyü sonlandır
print(i, end=" ") # 0 1 2 3 4
else:
print("Döngü normal bitti (break olmadı).") # Bu satır çalışmaz
print("\nDöngü sonrası")
print("\nContinue Örneği:")
for i in range(10):
if i % 2 == 0: # Eğer sayı çiftse
continue # Bu adımı atla, sonraki adıma geç
print(i, end=" ") # 1 3 5 7 9 (Sadece tek sayılar yazılır)
else:
print("\nDöngü normal bitti (break olmadı).") # Bu satır çalışır
print("\nDöngü sonrası")
print("\nPass Örneği:")
x = 150 # x'e bir değer atayalım
for i in range(3):
if i == 1:
pass # Henüz ne yapacağıma karar vermedim ama blok boş kalamaz
print("(i=1 için pass geçildi)")
else:
print(i)
if x > 100:
pass # Şimdilik bir şey yapma
else:
print("x 100'den küçük veya eşit")
Python Veri Yapıları: Koleksiyonlar
Python, birden fazla değeri bir arada tutmak ve yönetmek için güçlü ve esnek yerleşik veri yapıları (koleksiyonlar) sunar: Listeler, Demetler, Sözlükler ve Kümeler.
Listeler (Lists)
Sıralı, değiştirilebilir (mutable) ve farklı veri tiplerinden elemanlar içerebilen bir koleksiyondur. Köşeli parantezler [ ]
ile oluşturulur.
- Oluşturma:
liste = [1, "iki", 3.0, True]
- Erişim (Indexing): İlk eleman 0. index'tedir. Negatif indexler sondan başlar (
-1
son eleman). liste[0]
, liste[-1]
.
- Dilimleme (Slicing):
liste[start:stop:step]
ile alt listeler oluşturulur. start
dahil, stop
hariçtir. Orijinal listeyi değiştirmez. liste[1:3]
(1. ve 2. index), liste[:2]
(baştan 2. indexe kadar), liste[1:]
(1. indexten sona kadar), liste[:]
(tam kopya).
- Değiştirme:
liste[index] = yeni_deger
- Eleman Ekleme:
append(eleman)
: Listenin sonuna ekler.
insert(index, eleman)
: Belirtilen index'e ekler.
extend(baska_liste)
: Başka bir listenin elemanlarını sona ekler.
- Eleman Silme:
remove(deger)
: Belirtilen değere sahip ilk elemanı siler.
pop(index=-1)
: Belirtilen index'teki (varsayılan son) elemanı siler ve döndürür.
del liste[index]
: Belirtilen index'teki elemanı siler.
clear()
: Listenin tüm içeriğini siler.
- Diğer Metotlar:
index(deger)
, count(deger)
, sort()
(yerinde sıralar), reverse()
(yerinde ters çevirir), copy()
(yüzeysel kopya oluşturur).
- Operatörler:
+
(birleştirme), *
(tekrarlama).
len(liste)
: Eleman sayısını verir.
rakamlar = [1, 5, 2, 8, 2]
print(f"Liste: {rakamlar}")
print(f"İlk eleman: {rakamlar[0]}") # 1
print(f"Son eleman: {rakamlar[-1]}") # 2
print(f"Dilim [1:4]: {rakamlar[1:4]}") # [5, 2, 8]
rakamlar[1] = 99 # Değiştirme
print(f"Değiştirilmiş: {rakamlar}") # [1, 99, 2, 8, 2]
rakamlar.append(10)
print(f"Append(10): {rakamlar}") # [1, 99, 2, 8, 2, 10]
rakamlar.insert(2, 55)
print(f"Insert(2, 55): {rakamlar}") # [1, 99, 55, 2, 8, 2, 10]
rakamlar.remove(2) # İlk bulunan 2'yi siler
print(f"Remove(2): {rakamlar}") # [1, 99, 55, 8, 2, 10]
son_eleman = rakamlar.pop()
print(f"Pop(): {son_eleman}, Liste: {rakamlar}") # 10, [1, 99, 55, 8, 2]
del rakamlar[0]
print(f"del [0]: {rakamlar}") # [99, 55, 8, 2]
rakamlar.sort() # Yerinde sıralar
print(f"Sort(): {rakamlar}") # [2, 8, 55, 99]
rakamlar.reverse() # Yerinde ters çevirir
print(f"Reverse(): {rakamlar}") # [99, 55, 8, 2]
print(f"Eleman sayısı: {len(rakamlar)}") # 4
Demetler (Tuples)
Listelere benzer şekilde sıralı koleksiyonlardır ancak değiştirilemezler (immutable). Yani bir demet oluşturulduktan sonra elemanları eklenemez, silinemez veya değiştirilemez. Normal parantezler ( )
ile oluşturulurlar.
- Oluşturma:
demet = (1, "iki", 3.0)
. Tek elemanlı demet oluştururken sondaki virgül önemlidir: tek_elemanli = (5,)
.
- Erişim ve Dilimleme: Listelerle aynıdır.
demet[0]
, demet[-1]
, demet[1:3]
.
- Neden Kullanılır?
- Verilerin yanlışlıkla değiştirilmesini önlemek için (güvenlik).
- Sözlük anahtarı olarak kullanılabilirler (listeler kullanılamaz çünkü değiştirilebilirler).
- Listelere göre genellikle biraz daha hızlıdırlar (nadiren önemli bir fark yaratır).
- Fonksiyonlardan birden fazla değer döndürmek için sıkça kullanılırlar (yapı bozma ile kolayca alınabilir).
- Metotlar: Sadece
count()
ve index()
gibi içeriği değiştirmeyen metotları vardır.
koordinatlar = (10.5, 25.0, 100.0)
print(f"Koordinatlar: {koordinatlar}")
print(f"X: {koordinatlar[0]}")
# koordinatlar[0] = 11.0 # Hata! TypeError: 'tuple' object does not support item assignment
# Tek elemanlı tuple
tek = ("yalnız",)
print(type(tek)) # <class 'tuple'>
# Demet üzerinde döngü
for k in koordinatlar:
print(k)
# Fonksiyondan birden fazla değer döndürme
def min_max_bul(liste):
return min(liste), max(liste) # Otomatik olarak tuple döndürür
sayilar = [4, 1, 9, -2, 5]
en_kucuk, en_buyuk = min_max_bul(sayilar) # Yapı bozma ile alma
print(f"En Küçük: {en_kucuk}, En Büyük: {en_buyuk}")
Sözlükler (Dictionaries / dict)
Sırasız (Python 3.7+ sürümlerinde eklenme sırasını korur), değiştirilebilir ve anahtar-değer (key-value) çiftlerinden oluşan bir koleksiyondur. Anahtarlar benzersiz ve değiştirilemez tipte (genellikle string veya tuple) olmalıdır. Değerler ise herhangi bir tipte olabilir. Süslü parantezler { }
ile ve anahtar: deger
formatıyla oluşturulur.
- Oluşturma:
sozluk = {"ad": "Ali", "yas": 30, "sehir": "İstanbul"}
veya sozluk = dict(ad="Ali", yas=30)
.
- Erişim: Anahtarlar kullanılarak erişilir:
sozluk["ad"]
. Anahtar yoksa KeyError
verir.
get(anahtar, varsayilan=None)
Metodu: Anahtarla değer alır, anahtar yoksa hata vermek yerine varsayilan
değeri (varsayılanı None
) döndürür.
- Ekleme/Güncelleme:
sozluk[yeni_anahtar] = yeni_deger
veya sozluk.update({anahtar1: deger1, anahtar2: deger2})
.
- Silme:
pop(anahtar, varsayilan=HATA)
: Anahtara ait değeri siler ve döndürür. Anahtar yoksa ve varsayılan değer verilmemişse KeyError
verir.
del sozluk[anahtar]
: Anahtar-değer çiftini siler. Anahtar yoksa KeyError
verir.
popitem()
: Son eklenen anahtar-değer çiftini (Python 3.7+) siler ve tuple olarak döndürür.
clear()
: Sözlüğün içeriğini temizler.
- Anahtarları, Değerleri, Öğeleri Alma:
keys()
: Anahtarların bir görünümünü (view) döndürür.
values()
: Değerlerin bir görünümünü döndürür.
items()
: Anahtar-değer çiftlerinin (tuple olarak) bir görünümünü döndürür. Bu görünümler genellikle döngülerde kullanılır.
len(sozluk)
: Anahtar-değer çifti sayısını verir.
ogrenci = {
"ad": "Zeynep",
"numara": 123,
"bolum": "Bilgisayar Müh.",
"notlar": [85, 90, 78]
}
print(f"Öğrenci Adı: {ogrenci['ad']}")
print(f"Öğrenci Bölümü: {ogrenci.get('bolum')}")
print(f"Öğrenci Mezun Mu: {ogrenci.get('mezun_mu', False)}") # Anahtar yok, varsayılan False döner
# Güncelleme/Ekleme
ogrenci["numara"] = 456
ogrenci["sehir"] = "Ankara" # Yeni anahtar-değer ekleme
print(f"Güncellenmiş Öğrenci: {ogrenci}")
# Silme
cikarilan_notlar = ogrenci.pop("notlar")
print(f"Çıkarılan Notlar: {cikarilan_notlar}, Sözlük: {ogrenci}")
del ogrenci["sehir"]
print(f"Şehir Silindi: {ogrenci}")
# Döngü ile gezinme
print("\nAnahtarlar:")
for anahtar in ogrenci.keys():
print(anahtar)
print("\nDeğerler:")
for deger in ogrenci.values():
print(deger)
print("\nAnahtar-Değer Çiftleri:")
for key, value in ogrenci.items():
print(f"{key} -> {value}")
print(f"Eleman sayısı: {len(ogrenci)}")
Kümeler (Sets)
Sırasız, değiştirilebilir ve benzersiz elemanlardan oluşan bir koleksiyondur. Matematikteki küme kavramına benzer. Süslü parantezler { }
ile veya set()
fonksiyonu ile oluşturulur. Boş küme oluşturmak için {}
yerine set()
kullanılmalıdır ({}
boş sözlük oluşturur).
- Oluşturma:
kume = {1, 2, 3, "a", "b", 2}
(Sonuç: {1, 2, 3, 'a', 'b'}
- tekrarlar otomatik atılır). kume = set([1, 2, 2, 3])
.
- Eleman Ekleme:
add(eleman)
.
- Eleman Silme:
remove(eleman)
: Elemanı siler, eleman yoksa KeyError
verir.
discard(eleman)
: Elemanı siler, eleman yoksa hata vermez.
pop()
: Kümeden rastgele (aslında genellikle belirli bir sıraya göre ama garanti değil) bir elemanı siler ve döndürür.
clear()
: Kümeyi boşaltır.
- Küme İşlemleri:
- Birleşim:
kume1 | kume2
veya kume1.union(kume2)
- Kesişim:
kume1 & kume2
veya kume1.intersection(kume2)
- Fark:
kume1 - kume2
veya kume1.difference(kume2)
(kume1'de olup kume2'de olmayanlar)
- Simetrik Fark:
kume1 ^ kume2
veya kume1.symmetric_difference(kume2)
(sadece birinde olanlar)
- Diğer Metotlar:
issubset()
(alt küme mi?), issuperset()
(üst küme mi?), isdisjoint()
(kesişim boş mu?).
- Üyelik Kontrolü (
in
): Kümelerde eleman arama (eleman in kume
) listelere göre çok daha hızlıdır.
renkler1 = {"kırmızı", "yeşil", "mavi"}
renkler2 = set(["yeşil", "sarı", "kırmızı"]) # Listeden set oluşturma
print(f"Renkler 1: {renkler1}")
print(f"Renkler 2: {renkler2}")
renkler1.add("mor")
renkler2.discard("turuncu") # Hata vermez
# renkler2.remove("turuncu") # KeyError verir
print(f"Add/Discard sonrası: {renkler1}, {renkler2}")
# Küme İşlemleri
birlesim = renkler1 | renkler2
kesisim = renkler1 & renkler2
fark1 = renkler1 - renkler2
fark2 = renkler2 - renkler1
simetrik_fark = renkler1 ^ renkler2
print(f"Birleşim: {birlesim}")
print(f"Kesişim: {kesisim}")
print(f"Fark (Renkler1 - Renkler2): {fark1}")
print(f"Fark (Renkler2 - Renkler1): {fark2}")
print(f"Simetrik Fark: {simetrik_fark}")
print(f"'mavi' renkler1'de var mı? {'mavi' in renkler1}") # True
# Tekrarlanan elemanları listeden kaldırma
sayilar = [1, 2, 5, 2, 3, 5, 1, 4, 4]
benzersiz_sayilar = list(set(sayilar)) # Önce sete çevirip sonra listeye çevir
print(f"Benzersiz Sayılar: {benzersiz_sayilar}") # [1, 2, 3, 4, 5] (sıra değişebilir)
Fonksiyonlar: Kodun Yapı Taşları
Fonksiyonlar, belirli bir görevi yerine getiren, tekrar tekrar çağrılabilen, isimlendirilmiş kod bloklarıdır. Python'da fonksiyonlar birinci sınıf nesnelerdir, yani değişkenlere atanabilir, başka fonksiyonlara argüman olarak geçilebilir ve fonksiyonlardan değer olarak döndürülebilirler.
Fonksiyon Tanımlama ve Çağırma (def
, return
)
Fonksiyonlar def
anahtar kelimesi ile tanımlanır, ardından fonksiyon adı, parantez içinde parametre listesi ve iki nokta üst üste (:
) gelir. Fonksiyon gövdesi girintili olmalıdır.
return
ifadesi, fonksiyondan bir değer döndürmek ve fonksiyonun çalışmasını sonlandırmak için kullanılır. Eğer return
kullanılmazsa veya return
'den sonra bir değer belirtilmezse, fonksiyon varsayılan olarak None
döndürür.
# Parametresiz, değer döndürmeyen fonksiyon
def selamla():
"""Bu fonksiyon basit bir selamlama mesajı yazdırır.""" # Docstring
print("Merhaba!")
# Parametreli, değer döndüren fonksiyon
def topla(sayi1, sayi2):
"""Verilen iki sayıyı toplar ve sonucu döndürür."""
sonuc = sayi1 + sayi2
return sonuc
# Fonksiyonları çağırma
selamla() # Çıktı: Merhaba!
toplam_sonucu = topla(15, 7)
print(f"Toplama Sonucu: {toplam_sonucu}") # Çıktı: Toplama Sonucu: 22
def kontrol_et(deger):
if deger > 10:
return "Büyük"
# Eğer return'e girmezse None döner
print("Kontrol devam ediyor...") # Bu satır deger <= 10 ise çalışır
print(kontrol_et(20)) # Çıktı: Büyük
print(kontrol_et(5)) # Çıktı: Kontrol devam ediyor... \n None
Fonksiyon başlığının hemen altındaki üç tırnaklı string (docstring), fonksiyonun ne yaptığını açıklamak için kullanılır ve help(fonksiyon_adi)
veya araçlar tarafından kullanılabilir.
Parametre Türleri ve Argümanlar
Fonksiyonlara veri aktarmanın farklı yolları vardır:
- Konumsal Argümanlar (Positional Arguments): Fonksiyon çağrılırken argümanlar, tanımda belirtilen parametre sırasına göre eşleştirilir.
- Anahtar Kelimeli Argümanlar (Keyword Arguments): Fonksiyon çağrılırken
parametre_adi=deger
şeklinde argümanlar verilir. Sıra önemli değildir.
- Varsayılan Parametre Değerleri: Fonksiyon tanımında parametreye
parametre=varsayılan_deger
şeklinde bir değer atanır. Fonksiyon çağrılırken o argüman verilmezse bu varsayılan değer kullanılır. Varsayılan değerli parametreler, konumsal parametrelerden sonra gelmelidir.
*args
(Değişken Sayıda Konumsal Argüman): Fonksiyon tanımında parametre adının başına *
konulur. Bu, fonksiyona geçirilen tüm "fazla" konumsal argümanları bir demet (tuple) içinde toplar.
**kwargs
(Değişken Sayıda Anahtar Kelimeli Argüman): Fonksiyon tanımında parametre adının başına **
konulur. Bu, fonksiyona geçirilen tüm "fazla" anahtar kelimeli argümanları bir sözlük (dictionary) içinde toplar.
*args
ve **kwargs
genellikle birlikte kullanılır ve sırasıyla konumsal ve anahtar kelimeli parametrelerden sonra gelmelidir.
def bilgi_yazdir(ad, sehir, yas=30, ulke="Türkiye"): # yas ve ulke varsayılan değerli
print(f"Ad: {ad}, Yaş: {yas}, Şehir: {sehir}, Ülke: {ulke}")
# Konumsal argümanlarla çağırma
bilgi_yazdir("Ahmet", "İstanbul")
# Çıktı: Ad: Ahmet, Yaş: 30, Şehir: İstanbul, Ülke: Türkiye
# Anahtar kelimeli argümanlarla çağırma (sıra farklı olabilir)
bilgi_yazdir(yas=25, ad="Ayşe", sehir="İzmir")
# Çıktı: Ad: Ayşe, Yaş: 25, Şehir: İzmir, Ülke: Türkiye
# Hem konumsal hem anahtar kelimeli (konumsallar önce gelmeli)
bilgi_yazdir("Mehmet", yas=40, sehir="Ankara")
# Çıktı: Ad: Mehmet, Yaş: 40, Şehir: Ankara, Ülke: Türkiye
def toplam_ve_ortalama(*sayilar): # *args
if not sayilar: # Eğer hiç sayı gönderilmediyse
return 0, 0.0
toplam = sum(sayilar)
ortalama = toplam / len(sayilar)
return toplam, ortalama
t, o = toplam_ve_ortalama(10, 20, 30, 40)
print(f"Toplam: {t}, Ortalama: {o}") # Toplam: 100, Ortalama: 25.0
def ayar_goster(**ayarlar): # **kwargs
print("\nAyar Detayları:")
if not ayarlar:
print("Ayar belirtilmemiş.")
return
for anahtar, deger in ayarlar.items():
print(f"- {anahtar}: {deger}")
ayar_goster(tema="koyu", dil="tr", fontSize=14)
ayar_goster()
def genel_fonksiyon(zorunlu_param, *args, **kwargs):
print(f"Zorunlu: {zorunlu_param}")
print(f"Ek Konumsal (*args): {args}")
print(f"Ek Anahtar Kelimeli (**kwargs): {kwargs}")
genel_fonksiyon(100, "ek1", "ek2", renk="mavi", boyut="L")
# Çıktı:
# Zorunlu: 100
# Ek Konumsal (*args): ('ek1', 'ek2')
# Ek Anahtar Kelimeli (**kwargs): {'renk': 'mavi', 'boyut': 'L'}
Kapsam (Scope) ve LEGB Kuralı
Python'da bir değişkene erişilmeye çalışıldığında, yorumlayıcı değişkeni bulmak için belirli bir sıra izler. Bu sıraya LEGB kuralı denir:
- L (Local): Önce değişkenin içinde bulunulan mevcut fonksiyonda tanımlanıp tanımlanmadığına bakılır.
- E (Enclosing Function Locals): Eğer yerel kapsamda bulunamazsa, içinde bulunulan fonksiyonu kapsayan dış fonksiyonların kapsamlarına (eğer varsa, iç içe fonksiyonlar durumunda) bakılır.
- G (Global): Eğer kapsayan fonksiyonlarda da bulunamazsa, modül seviyesindeki (global) kapsama bakılır.
- B (Built-in): Eğer global kapsamda da bulunamazsa, Python'un yerleşik isimlerine (
print
, len
, str
gibi fonksiyonlar ve tipler) bakılır.
Eğer değişken hiçbir kapsamda bulunamazsa NameError
hatası alınır.
Normalde fonksiyon içinden global bir değişkenin değeri okunabilir, ancak değiştirilmeye çalışılırsa, Python o isimde yeni bir yerel değişken oluşturur (eğer global değişkenle aynı isimde bir atama yapılırsa). Global bir değişkenin değerini fonksiyon içinden gerçekten değiştirmek için global
anahtar kelimesi kullanılır. Benzer şekilde, kapsayan bir fonksiyondaki değişkeni değiştirmek için nonlocal
anahtar kelimesi kullanılır.
x = "global x"
def dis_fonksiyon():
y = "dış y"
# x = "dış fonksiyon x" # Bu yeni bir yerel x oluşturur, global x'i değiştirmez
def ic_fonksiyon():
z = "iç z"
# y = "iç fonksiyon y" # Bu yeni bir yerel y oluşturur, dış y'yi değiştirmez
# nonlocal y # Bu satır eklenirse dıştaki y değiştirilir
# y = "iç fonksiyon y (nonlocal)"
# global x # Bu satır eklenirse global x değiştirilir
# x = "iç fonksiyon x (global)"
print(f"İç fonksiyon içi: x={x}, y={y}, z={z}") # x globalden, y dış fonksiyondan gelir
ic_fonksiyon()
print(f"Dış fonksiyon içi: x={x}, y={y}") # z'ye erişilemez
dis_fonksiyon()
print(f"Global alan: x={x}") # y ve z'ye erişilemez
# global ve nonlocal kullanılsaydı global x ve dış y'nin değeri değişirdi.
Lambda Fonksiyonları
İsimsiz (anonim), tek bir ifade içeren ve bu ifadenin sonucunu döndüren küçük fonksiyonlar oluşturmak için kullanılır. lambda arguments: expression
sözdizimine sahiptir.
Genellikle başka fonksiyonlara argüman olarak (örneğin sort
, map
, filter
gibi) kısa bir işlem tanımlamak gerektiğinde kullanılırlar.
# İki sayıyı toplayan lambda
topla = lambda a, b: a + b
print(topla(5, 3)) # 8
# Tek argümanlı lambda
karesini_al = lambda x: x * x
print(karesini_al(6)) # 36
# map() ile kullanım: Listedeki her elemanın karesini alma
sayilar = [1, 2, 3, 4, 5]
kareler = list(map(lambda x: x * x, sayilar))
print(kareler) # [1, 4, 9, 16, 25]
# filter() ile kullanım: Listedeki çift sayıları filtreleme
cift_sayilar = list(filter(lambda x: x % 2 == 0, sayilar))
print(cift_sayilar) # [2, 4]
# sorted() ile kullanım: Listeyi elemanların ikinci harfine göre sıralama
isimler = ["Ali", "Zeynep", "Can", "Bora"]
sirali_isimler = sorted(isimler, key=lambda isim: isim[1]) # İkinci harfe göre sırala
print(sirali_isimler) # ['Can', 'Ali', 'Zeynep', 'Bora']
Lambda fonksiyonları basit işlemler için kullanışlıdır, ancak karmaşık mantıklar için normal def
ile tanımlanmış fonksiyonlar daha okunabilirdir.
Modüller ve Paketler: Kodu Organize Etme ve Yeniden Kullanma
Python'un gücünün önemli bir kısmı, kodun modüller ve paketler halinde organize edilerek yeniden kullanılabilmesinden gelir. Bu, büyük projelerin yönetimini kolaylaştırır ve başkaları tarafından yazılmış hazır çözümlerden (standart kütüphane ve üçüncü parti paketler) yararlanmayı sağlar.
Modül Nedir ve Nasıl Kullanılır?
Bir modül, Python tanımları ve ifadeleri içeren basit bir .py
dosyasıdır. İçinde fonksiyonlar, sınıflar ve değişkenler barındırabilir. Başka bir Python script'inden bu modüldeki kodları kullanmak için import
ifadesi kullanılır.
Farklı import
yöntemleri:
import modul_adi
: Tüm modülü içe aktarır. Modül içindeki nesnelere erişmek için modul_adi.nesne_adi
kullanılır. Bu genellikle isim çakışmalarını önlediği için tercih edilir.
from modul_adi import nesne1, nesne2
: Modülden sadece belirtilen nesneleri (fonksiyon, sınıf vb.) doğrudan mevcut isim alanına aktarır. Bu nesnelere doğrudan isimleriyle erişilebilir.
from modul_adi import *
: Modüldeki tüm public isimleri (_
ile başlamayanları) mevcut isim alanına aktarır. İsim çakışmalarına yol açabileceği ve kodun okunabilirliğini azaltabileceği için genellikle önerilmez.
import modul_adi as takma_ad
: Modülü farklı bir isimle (takma ad) içe aktarır. Özellikle uzun modül isimleri için kullanışlıdır.
from modul_adi import nesne as takma_ad
: Modülden belirli bir nesneyi farklı bir isimle içe aktarır.
Örnek: hesaplamalar.py
adında bir modülümüz olsun:
# hesaplamalar.py
PI = 3.14159
def topla(a, b):
return a + b
def carp(a, b):
return a * b
class HesapMakinesi:
def bol(self, a, b):
if b == 0:
return "Sıfıra bölme hatası"
return a / b
Bu modülü başka bir dosyada kullanma (ana_script.py
):
# ana_script.py
# Yöntem 1: Tüm modülü import etme
import hesaplamalar
print(hesaplamalar.PI)
print(hesaplamalar.topla(5, 3))
makine1 = hesaplamalar.HesapMakinesi()
print(makine1.bol(10, 2))
# Yöntem 2: Belirli nesneleri import etme
from hesaplamalar import PI, carp
print(PI) # Doğrudan erişim
print(carp(4, 6))
# Yöntem 3: Modüle takma ad verme
import hesaplamalar as hsp
print(hsp.PI)
makine2 = hsp.HesapMakinesi()
print(makine2.bol(9, 3))
# Yöntem 4: Nesneye takma ad verme
from hesaplamalar import HesapMakinesi as Calc
makine3 = Calc()
print(makine3.bol(12, 4))
Python, modülleri bulmak için belirli bir arama yolu (sys.path
) kullanır. Bu yol genellikle script'in bulunduğu dizini, PYTHONPATH çevre değişkeninde belirtilen dizinleri ve Python kurulum dizinindeki standart kütüphane yollarını içerir.
Python Standart Kütüphanesi
Python kurulumu ile birlikte gelen, çok çeşitli görevler için hazır modüller içeren zengin bir standart kütüphaneye sahiptir. Bu, harici paketlere ihtiyaç duymadan birçok temel işlevi yerine getirmenizi sağlar. Bazı önemli standart modüller:
math
: Matematiksel fonksiyonlar (sqrt
, sin
, cos
, log
, pi
, e
vb.).
random
: Rastgele sayı üretimi, liste karıştırma, rastgele seçim yapma (random
, randint
, choice
, shuffle
vb.).
datetime
: Tarih ve saat işlemleri (datetime
, date
, time
, timedelta
sınıfları).
os
: İşletim sistemi ile etkileşim (dosya/dizin işlemleri - listdir
, mkdir
, remove
, çevre değişkenleri - environ
, işlem yönetimi).
sys
: Python yorumlayıcısı ile ilgili bilgilere ve fonksiyonlara erişim (komut satırı argümanları - argv
, arama yolu - path
, çıkış - exit
).
json
: JSON verilerini işleme (load
, loads
, dump
, dumps
).
csv
: CSV dosyalarını okuma ve yazma.
re
: Düzenli ifadeler (Regular Expressions) ile metin işleme.
collections
: Ek veri yapıları sunar (defaultdict
, Counter
, deque
, namedtuple
).
urllib
/ requests
(harici ama çok yaygın): HTTP istekleri yapma. (requests
genellikle daha kullanıcı dostudur).
sqlite3
: SQLite veritabanı ile çalışma.
Bu modülleri kullanmak için sadece import
etmeniz yeterlidir.
import math
import random
from datetime import date
print(f"Pi sayısı: {math.pi}")
print(f"Karekök(16): {math.sqrt(16)}")
rastgele_sayi = random.randint(1, 100) # 1-100 arası rastgele tamsayı
print(f"Rastgele Sayı: {rastgele_sayi}")
bugun = date.today()
print(f"Bugünün tarihi: {bugun}")
print(f"Yıl: {bugun.year}")
Paketler ve pip
Bir paket, modüllerin ve alt paketlerin hiyerarşik olarak organize edildiği bir dizin yapısıdır. Paketler, büyük kütüphaneleri veya uygulamaları mantıksal bileşenlere ayırmayı sağlar. Bir dizinin paket olarak tanınması için genellikle içinde (boş bile olsa) bir __init__.py
dosyası bulunması gerekir (Python 3.3+ sürümlerinde bu dosya zorunlu olmasa da uyumluluk ve açıklık için hala yaygın olarak kullanılır).
Python'un standart kütüphanesi dışında kalan, topluluk tarafından geliştirilmiş milyonlarca paket Python Paket İndeksi'nde (PyPI - pypi.org) bulunur.
pip
: Bu paketleri PyPI'dan indirmek, kurmak, güncellemek ve kaldırmak için kullanılan komut satırı aracıdır.
- Paket Kurma:
pip install paket_adi
- Belirli Sürümü Kurma:
pip install paket_adi==1.2.3
- Paket Güncelleme:
pip install --upgrade paket_adi
- Paket Kaldırma:
pip uninstall paket_adi
- Kurulu Paketleri Listeleme:
pip list
- Paket Arama:
pip search sorgu
(Bu komut bazen kısıtlı çalışabilir, PyPI web sitesi daha güvenilirdir).
- Bağımlılıkları Dosyadan Kurma: Proje bağımlılıkları genellikle
requirements.txt
adlı bir dosyada listelenir. Bu dosyadaki tüm paketleri kurmak için: pip install -r requirements.txt
- Mevcut Ortamdaki Paketleri Dosyaya Yazma:
pip freeze > requirements.txt
Sanal ortamlar kullanmak, farklı projelerin farklı paket sürümlerine olan bağımlılıklarını yönetmek için kritiktir.
# Komut Satırı Örnekleri (Terminal/CMD)
# requests paketini kurma
pip install requests
# numpy paketinin 1.20.0 sürümünü kurma
pip install numpy==1.20.0
# requests paketini güncelleme
pip install --upgrade requests
# kurulu paketleri listeleme
pip list
# mevcut ortamdaki paketleri requirements.txt'ye yazma
pip freeze > requirements.txt
# requirements.txt dosyasındaki paketleri kurma
pip install -r requirements.txt
# requests paketini kaldırma
pip uninstall requests
Python'da Nesne Yönelimli Programlama (OOP)
Python, nesne yönelimli programlamayı tam olarak destekleyen bir dildir. OOP, kodu yeniden kullanılabilir nesneler etrafında modelleyerek daha organize, modüler ve yönetilebilir hale getirir.
Sınıflar (class
) ve Nesneler
Daha önce bahsedildiği gibi, sınıf bir şablon, nesne ise o şablonun somut bir örneğidir.
- Sınıf Tanımı:
class SinifAdi:
ile başlar. Genellikle sınıf isimleri BüyükHarfleBaşlar (CamelCase).
__init__(self, ...)
Metodu (Constructor): Sınıftan bir nesne oluşturulduğunda (SinifAdi(...)
çağrıldığında) otomatik olarak çalışan özel bir metottur. Genellikle nesnenin başlangıç niteliklerini (attributes) ayarlamak için kullanılır. İlk parametresi her zaman nesnenin kendisini temsil eden self
'tir.
- Nitelikler (Attributes): Nesnenin verileridir. Genellikle
__init__
içinde self.nitelik_adi = deger
şeklinde tanımlanır.
- Metotlar (Methods): Sınıf içinde tanımlanan fonksiyonlardır. Nesnenin davranışlarını belirlerler. İlk parametreleri her zaman
self
olmalıdır (nesnenin kendi niteliklerine ve diğer metotlarına erişmek için).
- Nesne Oluşturma (Instantiation):
nesne_degiskeni = SinifAdi(argümanlar)
şeklinde yapılır. Bu, __init__
metodunu çağırır.
- Niteliklere ve Metotlara Erişim: Nokta (
.
) notasyonu ile yapılır: nesne_degiskeni.nitelik_adi
, nesne_degiskeni.metot_adi(argümanlar)
.
class Araba:
# Sınıf Niteliği (Tüm Araba nesneleri için ortak)
tekerlek_sayisi = 4
def __init__(self, marka, model, yil, renk="Bilinmiyor"):
# Örnek Nitelikleri (Her nesne için ayrı)
self.marka = marka
self.model = model
self.yil = yil
self.renk = renk
self.hiz = 0
print(f"{self.yil} model {self.marka} {self.model} oluşturuldu.")
# Örnek Metotları
def hizlan(self, artis):
self.hiz += artis
print(f"Hız {self.hiz} km/s oldu.")
def yavasla(self, azalis):
self.hiz -= azalis
if self.hiz < 0:
self.hiz = 0
print(f"Hız {self.hiz} km/s oldu.")
def bilgi_goster(self):
print(f"Marka: {self.marka}, Model: {self.model}, Yıl: {self.yil}, Renk: {self.renk}, Hız: {self.hiz}")
print(f"Tekerlek Sayısı: {self.tekerlek_sayisi}") # Sınıf niteliğine erişim
# Nesneleri oluşturma
araba1 = Araba("Toyota", "Corolla", 2021, "Beyaz")
araba2 = Araba("Ford", "Focus", 2020)
# Metotları çağırma
araba1.hizlan(50)
araba2.hizlan(30)
araba1.yavasla(20)
araba1.bilgi_goster()
araba2.bilgi_goster()
# Niteliklere doğrudan erişim (genellikle önerilmez, kapsülleme tercih edilir)
# print(araba1.marka)
# araba1.hiz = 100 # Doğrudan değiştirme
# Sınıf niteliğine erişim
print(f"Araba Tekerlek Sayısı: {Araba.tekerlek_sayisi}")
Kalıtım (Inheritance)
Bir sınıfın başka bir sınıfın özelliklerini ve metotlarını miras almasıdır.
- Tanımlama:
class AltSinif(UstSinif):
- Alt sınıf, üst sınıfın tüm nitelik ve metotlarına (private olmayanlar -
__
ile başlamayanlar) erişebilir.
- Metot Geçersiz Kılma (Overriding): Alt sınıf, üst sınıftan miras aldığı bir metodu aynı isim ve parametrelerle yeniden tanımlayarak davranışını değiştirebilir.
super()
Fonksiyonu: Alt sınıf içinden, üst sınıfın metotlarına (özellikle __init__
metoduna) erişmek için kullanılır.
class ElektrikliAraba(Araba): # Araba sınıfından kalıtım alır
def __init__(self, marka, model, yil, batarya_kapasitesi, renk="Bilinmiyor"):
# Üst sınıfın __init__ metodunu çağırarak temel nitelikleri ayarla
super().__init__(marka, model, yil, renk)
self.batarya_kapasitesi = batarya_kapasitesi # Yeni nitelik
# Yeni metot
def sarj_et(self):
print(f"{self.marka} {self.model} şarj ediliyor ({self.batarya_kapasitesi} kWh)...")
# Üst sınıftaki metodu override etme
def bilgi_goster(self):
super().bilgi_goster() # Önce üst sınıfın metodunu çağır
print(f"Batarya Kapasitesi: {self.batarya_kapasitesi} kWh") # Ek bilgiyi yazdır
# Nesne oluşturma
elektrikli_arac = ElektrikliAraba("Tesla", "Model 3", 2022, 75, "Kırmızı")
elektrikli_arac.hizlan(80)
elektrikli_arac.sarj_et()
print("-" * 20)
elektrikli_arac.bilgi_goster() # Override edilmiş metot çalışır
Kapsülleme ve Properties
Kapsülleme, nesnenin iç durumunu korumak ve dışarıdan doğrudan erişimi kısıtlamak anlamına gelir. Python'da bu genellikle isimlendirme kuralları ve property'ler ile sağlanır:
- Tek Alt Çizgi (
_
): Bir nitelik veya metodun adının başına tek alt çizgi konulması (örn: self._gizli_veri
), o üyenin sınıfın "iç kullanımı için" olduğunu ve dışarıdan doğrudan erişilmemesi gerektiğini belirten bir konvansiyondur (kuraldır). Python erişimi teknik olarak engellemez, ancak geliştiricilere bir uyarıdır.
- Çift Alt Çizgi (
__
): Bir nitelik veya metodun adının başına çift alt çizgi konulması (örn: self.__cok_gizli
), Python'un "isim mangling" (isim bozma) yapmasına neden olur. Bu, nitelik adını çalışma zamanında _SinifAdi__cok_gizli
şeklinde değiştirerek alt sınıflarda yanlışlıkla override edilmesini veya dışarıdan doğrudan erişilmesini zorlaştırır. Tamamen gizlilik sağlamaz ama daha güçlü bir işarettir.
- Properties (
@property
Decorator): Metotları, nitelik gibi (parantez kullanmadan) erişilebilir hale getirmenin Pythonic yoludur. Bu, getter, setter ve deleter metotları tanımlayarak niteliklere erişimi kontrol etmeyi sağlar (kapsüllemeyi destekler).
@property
: Getter metodu için kullanılır.
@nitelik_adi.setter
: Setter metodu için kullanılır.
@nitelik_adi.deleter
: Deleter metodu için kullanılır.
class Calisan:
def __init__(self, ad, maas):
self.ad = ad # Public nitelik
self._departman = "Genel" # Korumalı (konvansiyon)
self.__maas = self._maas_kontrol(maas) # Özel (isim mangling)
def _maas_kontrol(self, maas): # İç kullanım için metot (konvansiyon)
if maas < 0:
print("Maaş negatif olamaz! 0 olarak ayarlandı.")
return 0
return maas
# Maas'a erişim için property (getter)
@property
def maas(self):
print("Maaş değeri okunuyor (getter)...")
return self.__maas
# Maas'ı değiştirmek için property (setter)
@maas.setter
def maas(self, yeni_maas):
print("Maaş değeri atanıyor (setter)...")
self.__maas = self._maas_kontrol(yeni_maas)
# Departmanı yöneten property
@property
def departman(self):
return self._departman
@departman.setter
def departman(self, yeni_departman):
if yeni_departman in ["IT", "İK", "Muhasebe", "Genel"]:
self._departman = yeni_departman
else:
print(f"Geçersiz departman: {yeni_departman}")
emp = Calisan("Veli", 5000)
print(emp.ad)
# print(emp.__maas) # Hata! Doğrudan erişilemez (AttributeError)
# print(emp._Calisan__maas) # İsim mangling ile erişilebilir ama önerilmez
# Property kullanımı (nitelik gibi erişim)
print(f"Maaş: {emp.maas}") # Getter çalışır
emp.maas = 6000 # Setter çalışır
print(f"Yeni Maaş: {emp.maas}")
emp.maas = -100 # Setter çalışır, kontrol yapılır
print(f"Negatif atama sonrası Maaş: {emp.maas}")
print(f"Departman: {emp.departman}")
emp.departman = "IT"
print(f"Yeni Departman: {emp.departman}")
emp.departman = "Satış" # Geçersiz departman uyarısı verir
Çok Biçimlilik ve Özel Metotlar
- Çok Biçimlilik (Polymorphism): Python'da genellikle "Duck Typing" (Ördek Tiplemesi) ile kendini gösterir: "Eğer bir şey ördek gibi yürüyorsa ve ördek gibi vaklıyorsa, o muhtemelen bir ördektir." Yani bir nesnenin belirli bir metoda sahip olup olmadığına bakılır, tipine değil. Kalıtım yoluyla metot override etme de çok biçimliliğin bir örneğidir.
- Özel Metotlar (Magic/Dunder Methods): Başında ve sonunda çift alt çizgi bulunan metotlardır (örn:
__init__
, __str__
, __len__
, __add__
). Python'un yerleşik davranışlarını (nesne oluşturma, string temsili, uzunluk, operatörler vb.) özelleştirmek için kullanılırlar.
__str__(self)
: print(nesne)
veya str(nesne)
çağrıldığında nesnenin kullanıcı dostu string temsilini döndürür.
__repr__(self)
: repr(nesne)
çağrıldığında veya interaktif kabukta nesne yazıldığında, nesnenin geliştirici dostu/teknik temsilini döndürür. __str__
yoksa bu kullanılır.
__len__(self)
: len(nesne)
çağrıldığında nesnenin uzunluğunu döndürür.
__add__(self, other)
: +
operatörünü nesneler için tanımlar.
__eq__(self, other)
: ==
operatörünü nesneler için tanımlar.
# Duck Typing Örneği
class Kedi:
def konus(self): print("Miyav")
class Kopek:
def konus(self): print("Hav hav")
class Insan:
def konuss(self): print("Merhaba") # Metot adı farklı
def hayvan_konustur(hayvan):
# Tip kontrolü yapmadan doğrudan metodu çağırmayı dene
try:
hayvan.konus()
except AttributeError:
print("Bu nesne 'konus' metoduna sahip değil.")
kedi = Kedi()
kopek = Kopek()
insan = Insan()
hayvan_konustur(kedi) # Miyav
hayvan_konustur(kopek) # Hav hav
hayvan_konustur(insan) # Bu nesne 'konus' metoduna sahip değil.
# Özel Metotlar Örneği
class Vektor:
def __init__(self, x, y):
self.x = x
self.y = y
def __str__(self): # Kullanıcı dostu temsil
return f"Vektör({self.x}, {self.y})"
def __repr__(self): # Teknik temsil
return f"Vektor(x={self.x}, y={self.y})"
def __add__(self, other): # + operatörünü tanımla
if isinstance(other, Vektor):
return Vektor(self.x + other.x, self.y + other.y)
return NotImplemented # Diğer tiplerle toplamayı desteklemiyorsak
def __len__(self): # len() fonksiyonunu tanımla
# Başlangıç noktasına uzaklık (örnek amaçlı)
import math
return int(math.sqrt(self.x**2 + self.y**2))
v1 = Vektor(2, 3)
v2 = Vektor(4, 1)
print(v1) # __str__ çağrılır: Vektör(2, 3)
print(repr(v2)) # __repr__ çağrılır: Vektor(x=4, y=1)
print(v1 + v2) # __add__ çağrılır: Vektör(6, 4)
print(len(v1)) # __len__ çağrılır (yaklaşık uzaklık): 3
Dosya İşlemleri: Veriyi Kalıcı Hale Getirme
Python, diskteki dosyaları okumak ve yazmak için basit ve güçlü araçlar sunar. Bu, programların verileri kalıcı olarak saklamasını ve başka programlarla veri alışverişi yapmasını sağlar.
Dosya Açma (open()
) ve Modlar
Bir dosyayla işlem yapmak için önce open(dosya_yolu, mod='r', encoding=None)
fonksiyonu ile açılması gerekir:
dosya_yolu
: Açılacak dosyanın adı ve yolu (string).
mod
(İsteğe bağlı): Dosyanın hangi amaçla açılacağını belirler. Yaygın modlar:
'r'
: Okuma modu (varsayılan). Dosya yoksa FileNotFoundError
verir.
'w'
: Yazma modu. Dosya varsa içeriğini siler, yoksa yeni dosya oluşturur.
'a'
: Ekleme modu (append). Dosya varsa sonuna ekler, yoksa yeni dosya oluşturur.
'x'
: Özel oluşturma modu. Dosya zaten varsa FileExistsError
verir, yoksa yazma modunda yeni dosya oluşturur.
'b'
: İkili (binary) mod. Metin olmayan dosyalar (resim, ses vb.) için moda eklenir (örn: 'rb'
, 'wb'
).
'+'
: Güncelleme modu (hem okuma hem yazma). Moda eklenir (örn: 'r+'
, 'w+'
, 'a+'
).
encoding
(İsteğe bağlı): Metin modunda kullanılacak karakter kodlamasını belirtir (örn: 'utf-8'
). Belirtilmezse işletim sisteminin varsayılanı kullanılır, ancak özellikle farklı sistemler arasında uyumluluk için 'utf-8'
belirtmek genellikle iyi bir fikirdir.
open()
fonksiyonu bir dosya nesnesi (file object) döndürür. İşlem bittikten sonra dosyanın close()
metodu ile kapatılması önemlidir (kaynakların serbest bırakılması için).
with
İfadesi ile Güvenli Dosya İşlemleri
Dosyaları manuel olarak close()
ile kapatmak unutulabilir veya hata durumlarında atlanabilir. with
ifadesi, bir bağlam yöneticisi (context manager) kullanarak bu sorunu çözer. with
bloğu sona erdiğinde (normal şekilde veya bir hata nedeniyle), dosya otomatik olarak kapatılır.
# with ifadesi ile dosya okuma (Önerilen Yöntem)
try:
with open("veri.txt", "r", encoding="utf-8") as dosya:
icerik = dosya.read() # Tüm içeriği oku
print("Dosya içeriği (with):\n", icerik)
# Bu noktada dosya otomatik olarak kapatılmıştır.
except FileNotFoundError:
print("Hata: veri.txt dosyası bulunamadı!")
except Exception as e:
print(f"Bir hata oluştu: {e}")
# with ifadesi ile dosyaya yazma
yazilacaklar = ["Satır 1\n", "Satır 2\n", "Türkçe karakterler: İıĞğŞşÖöÜü\n"]
try:
with open("cikti.txt", "w", encoding="utf-8") as f:
f.write("Bu ilk satır.\n") # Tek satır yazma
f.writelines(yazilacaklar) # Liste içeriğini satır satır yazma
print("cikti.txt dosyasına yazıldı.")
except Exception as e:
print(f"Yazma hatası: {e}")
# Manuel open/close (Daha az güvenli)
# dosya_obj = None
# try:
# dosya_obj = open("eski_yontem.txt", "r")
# # ... okuma işlemleri ...
# except Exception as e:
# print(f"Hata: {e}")
# finally:
# if dosya_obj:
# dosya_obj.close()
# print("Dosya manuel olarak kapatıldı.")
Dosya işlemleri için her zaman with
ifadesini kullanmak tercih edilir.
Dosya Okuma ve Yazma Metotları
Açık bir dosya nesnesi üzerinden çeşitli okuma ve yazma metotları kullanılır:
- Okuma Metotları (
'r'
veya 'r+'
modunda):
- Yazma Metotları (
'w'
, 'a'
, 'w+'
, 'a+'
modunda):
write(string)
: Verilen string'i dosyaya yazar. Yeni satır karakteri (\n
) otomatik eklemez.
writelines(liste)
: String listesindeki her bir string'i dosyaya yazar (aralara veya sonlara \n
eklemez, string'lerin kendisi içermelidir).
Hata Yönetimi (Exception Handling)
Program çalışırken dosya bulunamaması, geçersiz kullanıcı girdisi, ağ bağlantı sorunları gibi beklenmedik durumlar (hatalar veya istisnalar) oluşabilir. Hata yönetimi, bu tür durumları programın çökmesini önleyecek şekilde ele almayı sağlar.
try...except
Bloğu
Hata oluşturma potansiyeli olan kodlar try
bloğuna yazılır. Eğer bu blokta bir hata (exception) oluşursa, programın normal akışı durur ve Python uygun bir except
bloğu arar.
except HataTipi:
: Belirtilen HataTipi
(örn: FileNotFoundError
, ValueError
, TypeError
) veya onun alt türlerinden bir hata oluşursa bu blok çalışır.
except HataTipi as degisken:
: Yakalanan hata nesnesini bir değişkene (örn: e
) atayarak hata hakkında daha fazla bilgiye (e.args
gibi) erişmeyi sağlar.
except (HataTipi1, HataTipi2):
: Birden fazla hata tipini aynı blokta yakalamak için kullanılır.
except:
: Hiçbir hata tipi belirtilmezse, tüm hata türlerini yakalar. Bu genellikle önerilmez, çünkü belirli hataları ele almak yerine tüm hataları maskeleyebilir. En sona genel Exception
yazmak daha iyidir.
try:
sayi_str = input("Bir sayı girin: ")
sayi = int(sayi_str)
sonuc = 100 / sayi
print(f"100 / {sayi} = {sonuc}")
except ValueError:
print("Hata: Lütfen geçerli bir tam sayı girin.")
except ZeroDivisionError:
print("Hata: Sıfıra bölme yapılamaz.")
except Exception as e: # Diğer tüm beklenmedik hataları yakala
print(f"Beklenmedik bir hata oluştu: {type(e).__name__} - {e}")
print("Program devam ediyor...")
else
ve finally
Blokları
else
Bloğu: try
bloğunda hiçbir hata oluşmazsa, try
bloğu bittikten hemen sonra çalıştırılır. Hata durumunda çalışmaz.
finally
Bloğu: try
bloğunda hata oluşsa da oluşmasa da, try
, except
ve else
bloklarından sonra her zaman çalıştırılır. Genellikle kaynakları temizlemek (dosyaları kapatmak, ağ bağlantılarını sonlandırmak vb.) için kullanılır.
dosya_adi = "test_dosyasi.txt"
f = None # Dosya nesnesini dışarıda tanımla
try:
f = open(dosya_adi, "w", encoding="utf-8")
f.write("Bu bir testtir.\n")
# Hata simülasyonu:
# sonuc = 10 / 0
except IOError as e: # Dosya işlemleriyle ilgili hatalar
print(f"Dosya hatası: {e}")
except Exception as e:
print(f"Genel hata: {e}")
else:
# Hata oluşmazsa burası çalışır
print(f"'{dosya_adi}' dosyasına başarıyla yazıldı.")
finally:
# Her durumda çalışır
print("Finally bloğu çalışıyor...")
if f: # Dosya başarıyla açıldıysa
f.close()
print(f"'{dosya_adi}' dosyası kapatıldı.")
with
ifadesi, dosya işlemleri için finally
bloğunda close()
çağırma ihtiyacını ortadan kaldırır.
Hata Fırlatma (raise
)
Kendi özel hata durumlarınızı belirtmek veya belirli koşullar sağlandığında programın akışını bilinçli olarak durdurmak için raise
ifadesi kullanılır. Genellikle yerleşik hata sınıflarından (ValueError
, TypeError
, Exception
vb.) bir örnek fırlatılır veya kendi özel hata sınıflarınızı tanımlayabilirsiniz.
def yas_kontrol(yas):
if not isinstance(yas, int):
raise TypeError("Yaş tam sayı olmalıdır.")
if yas < 0:
raise ValueError("Yaş negatif olamaz.")
elif yas < 18:
print("Kullanıcı reşit değil.")
else:
print("Kullanıcı reşit.")
try:
yas_kontrol(25)
yas_kontrol(-5) # ValueError fırlatacak
yas_kontrol("abc") # Bu satıra ulaşılamayacak
except ValueError as ve:
print(f"Değer Hatası Yakalandı: {ve}")
except TypeError as te:
print(f"Tip Hatası Yakalandı: {te}")
# Kendi özel hata sınıfı
class BenimHatam(Exception):
pass
def ozel_islem(deger):
if deger == "yasak":
raise BenimHatam("Bu değere izin verilmiyor!")
print("İşlem başarılı.")
try:
ozel_islem("izinli")
ozel_islem("yasak")
except BenimHatam as bh:
print(f"Özel Hata Yakalandı: {bh}")
İleri Konular ve Python Ekosistemi
Python'un temellerini ve ana veri yapılarını öğrendikten sonra, dili daha etkili kullanmanızı sağlayacak ileri seviye özelliklere ve geniş ekosistemine göz atabilirsiniz.
Comprehensions (List, Dict, Set) ve Generator Expressions
Mevcut bir koleksiyon veya yinelenebilir (iterable) üzerinden yeni listeler, sözlükler veya kümeler oluşturmak için kısa ve okunabilir bir yol sunarlar.
- List Comprehension:
[ifade for eleman in iterable if koşul]
# 0-9 arası sayıların kareleri
kareler = [x**2 for x in range(10)] # [0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
# 0-9 arası çift sayıların kareleri
cift_kareler = [x**2 for x in range(10) if x % 2 == 0] # [0, 4, 16, 36, 64]
print(kareler)
print(cift_kareler)
- Dictionary Comprehension:
{anahtar_ifadesi: deger_ifadesi for eleman in iterable if koşul}
# Sayıların karelerini içeren sözlük
sayi_kare_sozluk = {x: x**2 for x in range(5)} # {0: 0, 1: 1, 2: 4, 3: 9, 4: 16}
print(sayi_kare_sozluk)
- Set Comprehension:
{ifade for eleman in iterable if koşul}
# Listedeki tek sayıların kümesi
sayilar = [1, 2, 2, 3, 4, 5, 5, 1]
tek_sayi_kumesi = {x for x in sayilar if x % 2 != 0} # {1, 3, 5}
print(tek_sayi_kumesi)
- Generator Expressions: List comprehension'a benzer ancak köşeli parantez yerine normal parantez kullanılır:
(ifade for eleman in iterable if koşul)
. Tüm listeyi bellekte oluşturmak yerine, ihtiyaç duyuldukça değer üreten bir generator nesnesi döndürür. Büyük veri setleri için bellek açısından daha verimlidir.
kareler_generator = (x**2 for x in range(1000000))
print(kareler_generator) # <generator object <genexpr> at ...>
# print(list(kareler_generator)) # Tümünü listeye çevirir (bellek kullanır)
print(sum(kareler_generator)) # Generator üzerinde işlem yapma (tek tek üretir)
Generators (yield
)
Generator'lar, değerleri tek tek üreten özel fonksiyonlardır. Normal fonksiyonlar gibi return
ile tek bir değer döndürmek yerine, yield
anahtar kelimesini kullanarak bir dizi değer üretebilirler. Her yield
çağrıldığında fonksiyonun durumu korunur ve bir sonraki çağrıda kaldığı yerden devam eder.
Büyük veri dizileri veya sonsuz diziler oluşturmak için bellek açısından çok verimlidirler, çünkü tüm değerleri aynı anda bellekte tutmazlar.
def cift_sayi_uret(limit):
sayi = 0
while sayi < limit:
yield sayi # Değeri üret ve fonksiyonun durumunu koru
sayi += 2
# Generator nesnesini oluştur
ciftler = cift_sayi_uret(10)
print(type(ciftler)) # <class 'generator'>
# Değerleri tek tek al
print(next(ciftler)) # 0
print(next(ciftler)) # 2
print(next(ciftler)) # 4
# Veya döngü ile
print("Kalan çift sayılar:")
for c in ciftler:
print(c) # 6, 8
Decorators (@
)
Decorator'lar, mevcut bir fonksiyonun veya metodun davranışını, kodunu doğrudan değiştirmeden sarmalayarak (wrap) veya değiştirerek genişletmek için kullanılan bir Python özelliğidir. Genellikle fonksiyonları argüman olarak alan ve yeni bir fonksiyon döndüren üst düzey fonksiyonlar olarak implemente edilirler. @decorator_adi
sözdizimi ile uygulanırlar.
Yaygın kullanım alanları: Logging (kayıt tutma), erişim kontrolü, zamanlama ölçümü, önbelleğe alma.
import time
# Basit bir decorator fonksiyonu
def zaman_olc(fonksiyon):
def wrapper(*args, **kwargs): # Orijinal fonksiyonun argümanlarını al
baslangic = time.time()
sonuc = fonksiyon(*args, **kwargs) # Orijinal fonksiyonu çalıştır
bitis = time.time()
print(f"'{fonksiyon.__name__}' fonksiyonu {bitis - baslangic:.4f} saniyede çalıştı.")
return sonuc
return wrapper
# Decorator'ı uygulama
@zaman_olc
def uzun_islem(n):
toplam = 0
for i in range(n):
toplam += i
return toplam
@zaman_olc
def baska_islem(a, b):
time.sleep(0.5) # 0.5 saniye bekle
return a + b
# Fonksiyonları çağırma (decorator otomatik olarak çalışır)
sonuc1 = uzun_islem(1000000)
# Çıktı: 'uzun_islem' fonksiyonu X.XXXX saniyede çalıştı.
sonuc2 = baska_islem(10, 20)
# Çıktı: 'baska_islem' fonksiyonu Y.YYYY saniyede çalıştı.
print(f"Sonuç 1: {sonuc1}")
print(f"Sonuç 2: {sonuc2}")
Popüler Alanlar ve Kütüphaneler (Kısa Bahis)
- Web Geliştirme:
- Django: Kapsamlı, "batteries-included" bir web framework'ü. Hızlı geliştirme, ORM, admin paneli gibi birçok özellik sunar. Büyük ve karmaşık projeler için idealdir.
- Flask: Mikro bir web framework'üdür. Daha basit ve esnektir, sadece temel yönlendirme ve istek/yanıt yönetimi sağlar. Eklentilerle genişletilebilir. Daha küçük projeler veya API'ler için popülerdir.
- FastAPI: Modern, hızlı, asenkron web framework'ü. API geliştirmeye odaklıdır, otomatik dökümantasyon (Swagger UI) ve veri doğrulama gibi özellikler sunar.
- Veri Bilimi ve Analiz:
- NumPy (Numerical Python): Çok boyutlu diziler (arrays) ve matrisler üzerinde yüksek performanslı matematiksel işlemler için temel kütüphane.
- Pandas: Veri manipülasyonu ve analizi için güçlü ve esnek veri yapıları (DataFrame, Series) sunar. Veri temizleme, işleme, birleştirme, gruplama gibi işlemler için vazgeçilmezdir.
- Matplotlib: Statik, dinamik ve interaktif veri görselleştirmeleri (grafikler, çizimler) oluşturmak için temel kütüphane.
- Seaborn: Matplotlib üzerine kurulu, daha çekici ve bilgilendirici istatistiksel grafikler oluşturmayı kolaylaştıran bir kütüphane.
- Makine Öğrenmesi ve Yapay Zeka:
- Scikit-learn: Sınıflandırma, regresyon, kümeleme, boyut azaltma gibi birçok makine öğrenmesi algoritmasını, model değerlendirme ve veri ön işleme araçlarını içeren popüler bir kütüphane.
- TensorFlow: Google tarafından geliştirilen, özellikle derin öğrenme (deep learning) için kullanılan açık kaynaklı güçlü bir kütüphane.
- PyTorch: Facebook (Meta) tarafından geliştirilen, TensorFlow'a popüler bir alternatif olan, esnek ve araştırmacılar arasında yaygın olarak kullanılan bir derin öğrenme kütüphanesi.
- Keras: TensorFlow veya diğer backend'ler üzerinde çalışan, derin öğrenme modellerini daha kolay oluşturmayı sağlayan üst düzey bir API.
- Otomasyon ve Scripting:
os
, sys
, shutil
, subprocess
gibi standart kütüphaneler veya requests
(web), BeautifulSoup
/Scrapy
(web scraping), Selenium
(web otomasyonu) gibi harici kütüphanelerle tekrarlayan görevleri otomatikleştirmek için sıkça kullanılır.
Python En İyi Uygulamaları (PEP 8 ve Ötesi)
- PEP 8'e Uyun: Python'un resmi stil rehberi olan PEP 8 (PEP 8), kodun okunabilir ve tutarlı olması için girintileme, isimlendirme kuralları, satır uzunluğu, boşluk kullanımı gibi konularda öneriler sunar. Linters (Flake8, Pylint) ve formatters (Black, Yapf) bu kurallara uymayı kolaylaştırır.
- Anlamlı İsimler Kullanın: Değişkenlere, fonksiyonlara ve sınıflara ne işe yaradıklarını açıkça belirten, okunabilir isimler verin (
kullanici_listesi
yerine kullanicilar
, hesapla
yerine vergiyi_hesapla
gibi).
- Okunabilir Kod Yazın: Basitliği hedefleyin. Karmaşık ifadeleri parçalara ayırın. Mantığı açıkça ifade edin. Pythonic (Python'a özgü doğal ve zarif) çözümleri tercih edin (örn: list comprehensions,
with
ifadesi).
- DRY (Don't Repeat Yourself): Kod tekrarından kaçının. Tekrar eden kod bloklarını fonksiyonlara veya sınıflara taşıyın.
- Yorumlar ve Docstrings: Kodun "neden"ini açıklamak için yorumlar, fonksiyonların/sınıfların/modüllerin "ne" yaptığını açıklamak için docstring'ler kullanın. Kodun kendisi "nasıl" yapıldığını açıklamalıdır.
- Sanal Ortamlar Kullanın: Her proje için ayrı bir sanal ortam kullanarak bağımlılıkları izole edin.
- Test Yazın: Kodunuzun doğru çalıştığından emin olmak ve gelecekteki değişikliklerde regresyonları (eski hataların tekrar oluşması) önlemek için birim testleri (unittest, pytest) yazın.
- Hata Yönetimini İhmal Etmeyin: Olası hataları öngörün ve
try...except
blokları ile uygun şekilde yönetin.
- Standart Kütüphaneyi İyi Öğrenin: Tekerleği yeniden icat etmeden önce, ihtiyacınız olan işlevselliğin standart kütüphanede olup olmadığını kontrol edin.
Sonuç: Python ile Sonsuz Olasılıklar
Python, öğrenmesi nispeten kolay, ancak son derece güçlü ve çok yönlü bir programlama dilidir. Temiz sözdizimi, geniş standart kütüphanesi ve devasa topluluk desteği sayesinde, web geliştirmeden yapay zekaya, veri analizinden otomasyona kadar akla gelebilecek hemen her alanda kullanılmaktadır.
Bu rehber, Python'un temel yapı taşlarından başlayarak önemli kavramları ve modern teknikleri kapsamlı bir şekilde ele almayı amaçladı. Ancak Python dünyası çok geniştir ve öğrenme süreci sürekli devam eder. Belirli bir alanda (web, veri bilimi vb.) uzmanlaşmak için ilgili framework ve kütüphaneleri derinlemesine öğrenmek, pratik projeler geliştirmek ve toplulukla etkileşimde bulunmak önemlidir.
Python'un okunabilirliği ve basitliği, onu programlamaya yeni başlayanlar için harika bir başlangıç noktası yaparken, sunduğu derinlik ve esneklik deneyimli geliştiriciler için de cazip kılmaktadır. Bu güçlü dili öğrenerek, teknoloji dünyasında kendinize sayısız kapı açabilir ve yaratıcı fikirlerinizi hayata geçirebilirsiniz.