Python Tiplerine Giriş¶
🌐 Yapay Zekâ ve İnsanlar Tarafından Çeviri
Bu çeviri, insanlar tarafından yönlendirilen bir yapay zekâ ile oluşturuldu. 🤝
Orijinal anlamın yanlış anlaşılması ya da kulağa doğal gelmeme gibi hatalar içerebilir. 🤖
Yapay zekâ LLM'ini daha iyi yönlendirmemize yardımcı olarak bu çeviriyi iyileştirebilirsiniz.
Python, isteğe bağlı "type hints" (diğer adıyla "type annotations") desteğine sahiptir.
Bu "type hints" veya annotations, bir değişkenin tip'ini bildirmeye yarayan özel bir sözdizimidir.
Değişkenleriniz için tip bildirerek, editörler ve araçlar size daha iyi destek sağlayabilir.
Bu, Python type hints hakkında sadece hızlı bir eğitim / bilgi tazeleme dokümanıdır. FastAPI ile kullanmak için gereken minimum bilgiyi kapsar... ki aslında bu çok azdır.
FastAPI tamamen bu type hints üzerine kuruludur; bunlar ona birçok avantaj ve fayda sağlar.
Ancak hiç FastAPI kullanmasanız bile, bunlar hakkında biraz öğrenmeniz size fayda sağlayacaktır.
Not
Eğer bir Python uzmanıysanız ve type hints hakkında her şeyi zaten biliyorsanız, sonraki bölüme geçin.
Motivasyon¶
Basit bir örnekle başlayalım:
def get_full_name(first_name, last_name):
full_name = first_name.title() + " " + last_name.title()
return full_name
print(get_full_name("john", "doe"))
Bu programı çalıştırınca şu çıktıyı alırsınız:
John Doe
Fonksiyon şunları yapar:
first_namevelast_namedeğerlerini alır.title()ile her birinin ilk harfini büyük harfe çevirir.- Ortada bir boşluk olacak şekilde Birleştirir.
def get_full_name(first_name, last_name):
full_name = first_name.title() + " " + last_name.title()
return full_name
print(get_full_name("john", "doe"))
Düzenleyelim¶
Bu çok basit bir program.
Ama şimdi bunu sıfırdan yazdığınızı hayal edin.
Bir noktada fonksiyon tanımını yazmaya başlamış olacaktınız, parametreler hazır...
Ama sonra "ilk harfi büyük harfe çeviren method"u çağırmanız gerekiyor.
upper mıydı? uppercase miydi? first_uppercase? capitalize?
Sonra eski programcı dostuyla denersiniz: editör autocomplete.
Fonksiyonun ilk parametresi olan first_name'i yazarsınız, sonra bir nokta (.) ve ardından autocomplete'i tetiklemek için Ctrl+Space'e basarsınız.
Ama ne yazık ki, işe yarar bir şey göremezsiniz:

Tipleri ekleyelim¶
Önceki sürümden tek bir satırı değiştirelim.
Fonksiyonun parametreleri olan şu parçayı:
first_name, last_name
şuna çevireceğiz:
first_name: str, last_name: str
Bu kadar.
Bunlar "type hints":
def get_full_name(first_name: str, last_name: str):
full_name = first_name.title() + " " + last_name.title()
return full_name
print(get_full_name("john", "doe"))
Bu, aşağıdaki gibi default değerler bildirmekle aynı şey değildir:
first_name="john", last_name="doe"
Bu farklı bir şey.
Eşittir (=) değil, iki nokta (:) kullanıyoruz.
Ve type hints eklemek, normalde onlarsız ne oluyorsa onu değiştirmez.
Ama şimdi, type hints ile o fonksiyonu oluşturmanın ortasında olduğunuzu tekrar hayal edin.
Aynı noktada, Ctrl+Space ile autocomplete'i tetiklemeye çalışırsınız ve şunu görürsünüz:

Bununla birlikte, seçenekleri görerek kaydırabilirsiniz; ta ki "tanıdık gelen" seçeneği bulana kadar:

Daha fazla motivasyon¶
Şu fonksiyona bakın, zaten type hints içeriyor:
def get_name_with_age(name: str, age: int):
name_with_age = name + " is this old: " + age
return name_with_age
Editör değişkenlerin tiplerini bildiği için, sadece completion değil, aynı zamanda hata kontrolleri de alırsınız:

Artık bunu düzeltmeniz gerektiğini, age'i str(age) ile string'e çevirmeniz gerektiğini biliyorsunuz:
def get_name_with_age(name: str, age: int):
name_with_age = name + " is this old: " + str(age)
return name_with_age
Tipleri Bildirmek¶
Type hints bildirmek için ana yeri az önce gördünüz: fonksiyon parametreleri.
Bu, FastAPI ile kullanırken de onları en çok kullanacağınız yerdir.
Basit tipler¶
Sadece str değil, tüm standart Python tiplerini bildirebilirsiniz.
Örneğin şunları kullanabilirsiniz:
intfloatboolbytes
def get_items(item_a: str, item_b: int, item_c: float, item_d: bool, item_e: bytes):
return item_a, item_b, item_c, item_d, item_e
typing modülü¶
Bazı ek kullanım durumları için standart kütüphanedeki typing modülünden bazı şeyleri import etmeniz gerekebilir. Örneğin bir şeyin "herhangi bir tip" olabileceğini bildirmek istediğinizde, typing içindeki Any'yi kullanabilirsiniz:
from typing import Any
def some_function(data: Any):
print(data)
Generic tipler¶
Bazı tipler, köşeli parantez içinde "type parameters" alarak iç tiplerini tanımlayabilir; örneğin "string listesi" list[str] olarak bildirilir.
Bu şekilde type parameter alabilen tiplere Generic types veya Generics denir.
Aynı builtin tipleri generics olarak kullanabilirsiniz (köşeli parantez ve içinde tiplerle):
listtuplesetdict
List¶
Örneğin, str'lerden oluşan bir list olan bir değişken tanımlayalım.
Değişkeni, aynı iki nokta (:) sözdizimiyle bildirin.
Tip olarak list yazın.
list, bazı iç tipleri barındıran bir tip olduğundan, bunları köşeli parantez içine yazarsınız:
def process_items(items: list[str]):
for item in items:
print(item)
Bilgi
Köşeli parantez içindeki bu iç tiplere "type parameters" denir.
Bu durumda str, list'e verilen type parameter'dır.
Bu şu demektir: "items değişkeni bir list ve bu listedeki her bir öğe str".
Bunu yaparak, editörünüz listeden öğeleri işlerken bile destek sağlayabilir:

Tipler olmadan, bunu başarmak neredeyse imkansızdır.
item değişkeninin, items listesindeki elemanlardan biri olduğuna dikkat edin.
Ve yine de editör bunun bir str olduğunu bilir ve buna göre destek sağlar.
Tuple ve Set¶
tuple'ları ve set'leri bildirmek için de aynısını yaparsınız:
def process_items(items_t: tuple[int, int, str], items_s: set[bytes]):
return items_t, items_s
Bu şu anlama gelir:
items_tdeğişkeni 3 öğeli birtuple'dır: birint, bir başkaintve birstr.items_sdeğişkeni birset'tir ve her bir öğesibytestipindedir.
Dict¶
Bir dict tanımlamak için, virgülle ayrılmış 2 type parameter verirsiniz.
İlk type parameter, dict'in key'leri içindir.
İkinci type parameter, dict'in value'ları içindir:
def process_items(prices: dict[str, float]):
for item_name, item_price in prices.items():
print(item_name)
print(item_price)
Bu şu anlama gelir:
pricesdeğişkeni birdict'tir:- Bu
dict'in key'leristrtipindedir (örneğin her bir öğenin adı). - Bu
dict'in value'larıfloattipindedir (örneğin her bir öğenin fiyatı).
- Bu
Union¶
Bir değişkenin birkaç tipten herhangi biri olabileceğini bildirebilirsiniz; örneğin bir int veya bir str.
Bunu tanımlamak için, her iki tipi ayırmak üzere dikey çizgi (|) kullanırsınız.
Buna "union" denir, çünkü değişken bu iki tip kümesinin birleşimindeki herhangi bir şey olabilir.
def process_item(item: int | str):
print(item)
Bu, item'ın int veya str olabileceği anlamına gelir.
Muhtemelen None¶
Bir değerin str gibi bir tipi olabileceğini ama aynı zamanda None da olabileceğini bildirebilirsiniz.
def say_hi(name: str | None = None):
if name is not None:
print(f"Hey {name}!")
else:
print("Hello World")
Sadece str yerine str | None kullanmak, aslında değer None olabilecekken her zaman str olduğunu varsaydığınız hataları editörün yakalamanıza yardımcı olur.
Tip olarak sınıflar¶
Bir sınıfı da bir değişkenin tipi olarak bildirebilirsiniz.
Örneğin, adı olan bir Person sınıfınız olsun:
class Person:
def __init__(self, name: str):
self.name = name
def get_person_name(one_person: Person):
return one_person.name
Sonra bir değişkeni Person tipinde olacak şekilde bildirebilirsiniz:
class Person:
def __init__(self, name: str):
self.name = name
def get_person_name(one_person: Person):
return one_person.name
Ve sonra, yine tüm editör desteğini alırsınız:

Bunun "one_person, Person sınıfının bir instance'ıdır" anlamına geldiğine dikkat edin.
"one_person, Person adlı class'tır" anlamına gelmez.
Pydantic modelleri¶
Pydantic, data validation yapmak için bir Python kütüphanesidir.
Verinin "shape"'ini attribute'lara sahip sınıflar olarak tanımlarsınız.
Ve her attribute'un bir tipi vardır.
Ardından o sınıfın bir instance'ını bazı değerlerle oluşturursunuz; bu değerleri doğrular, uygun tipe dönüştürür (gerekliyse) ve size tüm veriyi içeren bir nesne verir.
Ve bu ortaya çıkan nesne ile tüm editör desteğini alırsınız.
Resmî Pydantic dokümanlarından bir örnek:
from datetime import datetime
from pydantic import BaseModel
class User(BaseModel):
id: int
name: str = "John Doe"
signup_ts: datetime | None = None
friends: list[int] = []
external_data = {
"id": "123",
"signup_ts": "2017-06-01 12:22",
"friends": [1, "2", b"3"],
}
user = User(**external_data)
print(user)
# > User id=123 name='John Doe' signup_ts=datetime.datetime(2017, 6, 1, 12, 22) friends=[1, 2, 3]
print(user.id)
# > 123
Bilgi
Daha fazlasını öğrenmek için Pydantic'in dokümanlarına bakın.
FastAPI tamamen Pydantic üzerine kuruludur.
Bunların pratikte nasıl çalıştığını Eğitim - Kullanım Kılavuzu içinde çok daha fazla göreceksiniz.
Metadata Annotations ile Type Hints¶
Python'da ayrıca, Annotated kullanarak bu type hints içine ek üstveri koymayı sağlayan bir özellik de vardır.
Annotated'ı typing içinden import edebilirsiniz.
from typing import Annotated
def say_hello(name: Annotated[str, "this is just metadata"]) -> str:
return f"Hello {name}"
Python'un kendisi bu Annotated ile bir şey yapmaz. Editörler ve diğer araçlar için tip hâlâ str'dir.
Ama FastAPI'ye uygulamanızın nasıl davranmasını istediğinize dair ek metadata sağlamak için Annotated içindeki bu alanı kullanabilirsiniz.
Hatırlanması gereken önemli nokta: Annotated'a verdiğiniz ilk type parameter, gerçek tiptir. Geri kalanı ise diğer araçlar için metadatadır.
Şimdilik, sadece Annotated'ın var olduğunu ve bunun standart Python olduğunu bilmeniz yeterli. 😎
İleride bunun ne kadar güçlü olabildiğini göreceksiniz.
İpucu
Bunun standart Python olması, editörünüzde mümkün olan en iyi developer experience'ı almaya devam edeceğiniz anlamına gelir; kodu analiz etmek ve refactor etmek için kullandığınız araçlarla da, vb. ✨
Ayrıca kodunuzun pek çok başka Python aracı ve kütüphanesiyle çok uyumlu olacağı anlamına gelir. 🚀
FastAPI'de type hints¶
FastAPI, birkaç şey yapmak için bu type hints'ten faydalanır.
FastAPI ile type hints kullanarak parametreleri bildirirsiniz ve şunları elde edersiniz:
- Editör desteği.
- Tip kontrolleri.
...ve FastAPI aynı bildirimleri şunlar için de kullanır:
- Gereksinimleri tanımlamak: request path parameters, query parameters, headers, bodies, bağımlılıklar (dependencies), vb.
- Veriyi dönüştürmek: request'ten gerekli tipe.
- Veriyi doğrulamak: her request'ten gelen veriyi:
- Veri geçersiz olduğunda client'a dönen otomatik hatalar üretmek.
- OpenAPI kullanarak API'yi dokümante etmek:
- bu, daha sonra otomatik etkileşimli dokümantasyon kullanıcı arayüzleri tarafından kullanılır.
Bunların hepsi kulağa soyut gelebilir. Merak etmeyin. Tüm bunları Eğitim - Kullanım Kılavuzu içinde çalışırken göreceksiniz.
Önemli olan, standart Python tiplerini tek bir yerde kullanarak (daha fazla sınıf, decorator vb. eklemek yerine), FastAPI'nin sizin için işin büyük kısmını yapmasıdır.
Bilgi
Tüm tutorial'ı zaten bitirdiyseniz ve tipler hakkında daha fazlasını görmek için geri döndüyseniz, iyi bir kaynak: mypy'nin "cheat sheet"i.