Type Conversion: int, float, str, bool, list, dict, set, bytes — Cast'in 8 Yüzü
Python'da bir değeri başka tipe dönüştürmek genelde tek satır: int('42'), float(3), str(123). Ama detaylar var: __int__/__float__/__str__ magic methods, hangi dönüşüm hata atar, NumPy/pandas dtype'ları, datetime parsing, JSON serialization. Bu derste 'cast'ın 8 yaygın senaryosu, custom class'lar için cast desteği, ve Pydantic gibi modern data validation kütüphanelerinin nasıl çalıştığı.
Şükrü Yusuf KAYA
22 dakikalık okuma
Orta🔄 Type conversion her satırda var
API yanıtından gelen string'i int'e çevir. CSV'den okunan değeri float'a. Form input'unu bool'a. Veri akışı varsa cast vardır. Bu derste 8 ana cast yöntemini, hangi dönüşümlerin başarısız olabileceğini, ve modern Python'un (Pydantic, dataclass) cast'ı otomatize eden yollarını öğreniyoruz.
Implicit (otomatik) vs Explicit (manuel)#
Python'da iki tür dönüşüm var:
Implicit: Python kendisi yapıyor.
# int + float → float print(5 + 3.14) # 8.14 (int otomatik float'a) # bool + int → int print(True + 1) # 2 (bool int alt sınıfı, dönüşüm trivial) # int → complex print(complex(3) + 4j) # (3+4j) # Kısmi: numeric promotion zinciri # bool < int < float < complex
Python "numeric tower" denilen bir hiyerarşi izliyor: . Otomatik üst tipe çıkarıyor.
bool ⊂ int ⊂ float ⊂ complexExplicit: Sen söylüyorsun.
print(int("42")) # 42 print(float("3.14")) # 3.14 print(str(123)) # "123" print(bool(0)) # False print(list("abc")) # ['a', 'b', 'c']
🚨 String ile sayı arası implicit yok:
print("5" + 3) # TypeError: can only concatenate str (not "int") to str print("5" + str(3)) # "53" (explicit) print(int("5") + 3) # 8
JavaScript bu noktada cömert (); Python katı — explicit zorunluluğu Pythonic'in 'açıklık iyiden iyidir' prensibine uyumlu.
"5" + 3 === "53"int() — sayıyı integer'a çevir#
int()# Float'tan (truncation — sıfıra doğru) print(int(3.7)) # 3 print(int(-3.7)) # -3 (NOT -4 — int floor değil, truncate) print(int(3.99)) # 3 # String'ten (10 tabanı default) print(int("42")) # 42 print(int(" 42 ")) # 42 (whitespace OK) print(int("-100")) # -100 print(int("+42")) # 42 (plus sign OK) # Geçersiz string # print(int("3.14")) # ValueError # print(int("abc")) # ValueError # print(int("")) # ValueError # print(int("12abc")) # ValueError (mixed) # Float string için iki adım print(int(float("3.14"))) # 3 # Farklı tabandan parse print(int("ff", 16)) # 255 (hex) print(int("777", 8)) # 511 (octal) print(int("1010", 2)) # 10 (binary) print(int("0xff", 16)) # 255 (prefix OK) print(int("0xff", 0)) # 255 (auto-detect from prefix) # Bool'dan print(int(True)) # 1 print(int(False)) # 0 # None'dan ve diğer # print(int(None)) # TypeError # print(int([1, 2])) # TypeError
🎯 üçüncü argüman base'i belirtir. Default 10. otomatik tanır (, , prefix'lerine bakar).
int(x, base)base=00x0b0oCustom class — __int__ ile cast desteği#
__int__class Celsius: def __init__(self, value): self.value = value def __int__(self): return int(round(self.value)) def __float__(self): return float(self.value) c = Celsius(36.7) print(int(c)) # 37 (yuvarlama) print(float(c)) # 36.7
__int____index__ — sequence indexing için#
__index__class CustomNum: def __init__(self, n): self.n = n def __index__(self): """list[obj] gibi indexlemede çağrılır.""" return self.n lst = [10, 20, 30, 40, 50] print(lst[CustomNum(2)]) # 30 (CustomNum'u index olarak kullandı) print(int(CustomNum(2))) # 2 (__index__ otomatik __int__ olarak da) # bin/hex/oct __index__'i kullanır (NOT __int__!) print(bin(CustomNum(10))) # '0b1010'
__index____int__float() — float'a çevir#
float()# Int'ten print(float(5)) # 5.0 # String'ten print(float("3.14")) # 3.14 print(float("3")) # 3.0 print(float("-2.5")) # -2.5 print(float("1e5")) # 100000.0 (scientific) print(float("1.5e-3")) # 0.0015 # Özel değerler print(float("inf")) # inf print(float("-inf")) # -inf print(float("nan")) # nan print(float("Inf")) # inf (case-insensitive) print(float("NAN")) # nan # Geçersiz # print(float("abc")) # ValueError # print(float("")) # ValueError # Bool'dan print(float(True)) # 1.0 print(float(False)) # 0.0 # Parametresiz (genelde 0.0 başlangıç) print(float()) # 0.0 # Custom class — __float__ class Money: def __init__(self, amount): self.amount = amount def __float__(self): return float(self.amount) m = Money(19.99) print(float(m)) # 19.99
🎯 parsing flexible: NaN, inf, scientific notation hepsi anlaşılıyor.
floatDecimal ve Fraction ile etkileşim#
DecimalFractionfrom decimal import Decimal from fractions import Fraction # Float → Decimal (DİKKAT — precision sızar) print(Decimal(0.1)) # Decimal('0.10000000000...') # String → Decimal (TEMİZ) print(Decimal('0.1')) # Decimal('0.1') # Decimal → float (precision kaybı potansiyeli) print(float(Decimal('0.1'))) # 0.1 # Float → Fraction print(Fraction(0.5)) # 1/2 print(Fraction(0.1)) # 3602879701896397/36028797018963968 (precision sızdı!) # String → Fraction print(Fraction('0.1')) # 1/10
Bu uyarıları önceki dersler hatırla (Modül 2/Ders 4-7). Float-tabanlı yaratım precision sızıntısına yol açar; string-tabanlı temiz.
str() — string'e çevir (her şey için)#
str()# Sayılar print(str(42)) # '42' print(str(3.14)) # '3.14' print(str(1e10)) # '10000000000.0' print(str(0.1 + 0.2)) # '0.30000000000000004' (float hassasiyetiyle) # Bool print(str(True)) # 'True' print(str(False)) # 'False' print(str(None)) # 'None' # Liste/dict — repr'i kullanır print(str([1, 2, 3])) # '[1, 2, 3]' print(str({"a": 1})) # "{'a': 1}" # Custom class — __str__ veya __repr__ class Point: def __init__(self, x, y): self.x = x self.y = y def __repr__(self): return f"Point({self.x}, {self.y})" def __str__(self): return f"({self.x}, {self.y})" p = Point(3, 4) print(str(p)) # (3, 4) — __str__ print(repr(p)) # Point(3, 4) — __repr__ # print() __str__ kullanıyor print(p) # (3, 4) # REPL __repr__ kullanıyor # >>> p # Point(3, 4)
__str____repr__format() ve f-string#
format()n = 42 # f-string — modern (3.6+) s = f"Sayı: {n}" # "Sayı: 42" # format spec s = f"{n:5d}" # " 42" (5-width, decimal) s = f"{n:05d}" # "00042" (zero-padded) s = f"{n:#06x}" # "0x002a" (hex with prefix) s = f"{3.14:.2f}" # "3.14" s = f"{3.14:10.2f}" # " 3.14" # str() default s = str(n) # "42" # format() built-in s = format(n, "5d") # " 42" s = format(n, "b") # "101010" (binary, no prefix) # Custom __format__ class Temp: def __init__(self, c): self.celsius = c def __format__(self, fmt): if fmt == "F": return f"{self.celsius * 9/5 + 32:.1f}°F" if fmt == "K": return f"{self.celsius + 273.15:.2f}K" return f"{self.celsius:.1f}°C" t = Temp(25) print(f"{t}") # 25.0°C (default) print(f"{t:F}") # 77.0°F print(f"{t:K}") # 298.15K
__format__bool() — truthiness ile cast#
bool()(Modül 2/Ders 8 hatırla)
# Falsy values print(bool(False)) # False print(bool(None)) # False print(bool(0)) # False print(bool(0.0)) # False print(bool("")) # False print(bool([])) # False print(bool({})) # False print(bool(set())) # False # Truthy print(bool(True)) # True print(bool(1)) # True print(bool(-1)) # True (sıfır olmayan int truthy) print(bool("x")) # True (boş olmayan string) print(bool([0])) # True (boş olmayan list) print(bool("False")) # True (içeriği "False" ama string boş değil) # Custom class — __bool__ veya __len__ class Container: def __init__(self, items): self.items = items def __bool__(self): return len(self.items) > 0 c1 = Container([]) c2 = Container([1, 2]) print(bool(c1)) # False print(bool(c2)) # True
🚨 → True — string'in içeriğine değil, varlığına bakıyor. JavaScript ile aynı, ama yeni başlayanın ilk tuzağı.
bool("False")Custom __bool__ ne zaman?#
__bool__# Dataclass'ta empty kontrolü from dataclasses import dataclass, field @dataclass class Cart: items: list = field(default_factory=list) def __bool__(self): return bool(self.items) cart = Cart() if cart: print("Sepet dolu") else: print("Sepet boş") # bunu yazar cart.items.append("x") if cart: print("Sepet dolu") # bunu yazar
if cart:if cart.items:Collection cast'ları: list, tuple, set, dict, frozenset#
# list — iterable'dan print(list("hello")) # ['h', 'e', 'l', 'l', 'o'] print(list((1, 2, 3))) # [1, 2, 3] print(list({1, 2, 3})) # [1, 2, 3] (set sıralanmamış) print(list({"a": 1, "b": 2})) # ['a', 'b'] (dict → keys) print(list(range(5))) # [0, 1, 2, 3, 4] print(list()) # [] (boş) # tuple print(tuple([1, 2, 3])) # (1, 2, 3) print(tuple("abc")) # ('a', 'b', 'c') # set — unique alıyor print(set([1, 2, 2, 3, 3, 3])) # {1, 2, 3} print(set("hello")) # {'e', 'h', 'l', 'o'} (unique chars) # frozenset — immutable set fs = frozenset([1, 2, 3]) print(fs) # frozenset({1, 2, 3}) # fs.add(4) # AttributeError: immutable # dict — key-value pair'lerden print(dict([("a", 1), ("b", 2)])) # {'a': 1, 'b': 2} print(dict(a=1, b=2)) # {'a': 1, 'b': 2} (keyword args) print(dict(zip(["a", "b"], [1, 2]))) # {'a': 1, 'b': 2} print(dict.fromkeys(["a", "b", "c"])) # {'a': None, 'b': None, 'c': None} print(dict.fromkeys(["a", "b"], 0)) # {'a': 0, 'b': 0} # Empty print(list()) # [] print(tuple()) # () print(set()) # set() print(dict()) # {}
🎯 list/tuple/set hepsi iterable alır. her karakteri eleman olarak alır.
set("hello")dict cast tuzakları#
# Dict'i list'e cast etmek key'leri verir d = {"a": 1, "b": 2, "c": 3} print(list(d)) # ['a', 'b', 'c'] print(list(d.keys())) # ['a', 'b', 'c'] — aynı print(list(d.values())) # [1, 2, 3] print(list(d.items())) # [('a', 1), ('b', 2), ('c', 3)] # Iterable of pairs → dict pairs = [("x", 1), ("y", 2)] print(dict(pairs)) # {'x': 1, 'y': 2} # Dict comprehension daha esnek {k: v for k, v in pairs} # aynı {k: v.upper() for k, v in [("a", "x"), ("b", "y")]} # {'a': 'X', 'b': 'Y'}
bytes ve bytearray — binary'e cast#
bytesbytearray# bytes — immutable byte dizisi print(bytes(5)) # b'\x00\x00\x00\x00\x00' (5 zero bytes) print(bytes([65, 66, 67])) # b'ABC' (int list → bytes) print(bytes("merhaba", "utf-8")) # b'merhaba' (string + encoding) print(bytes("İstanbul", "utf-8"))# b'\xc4\xb0stanbul' (Türkçe karakter) # bytearray — mutable ba = bytearray(b"hello") ba[0] = 72 # H (capital) print(ba) # bytearray(b'Hello') # str ↔ bytes text = "merhaba" encoded = text.encode("utf-8") # bytes decoded = encoded.decode("utf-8") # str # Hex'ten bytes print(bytes.fromhex("48656c6c6f")) # b'Hello' # Bytes hex olarak göster print(b"Hello".hex()) # '48656c6c6f' # Bytes int dizisine print(list(b"ABC")) # [65, 66, 67]
bytes/bytearray network programming, dosya I/O, kriptografi için. çağrıları her gün gördüğün şeyler. Modül 3/Ders 16 detaylı işliyor.
encode/decodeCustom __bytes__#
__bytes__class Packet: def __init__(self, header, payload): self.header = header self.payload = payload def __bytes__(self): return self.header.encode("ascii") + b"\x00" + self.payload p = Packet("HELLO", b"world") print(bytes(p)) # b'HELLO\x00world'
Pratik 1: API'den CSV'ye veri akışı#
Gerçek dünyada cast pattern'leri:
import csv from datetime import datetime from decimal import Decimal def parse_order_row(row: dict) -> dict: """CSV string'lerini doğru tiplere cast et.""" return { "id": int(row["id"]), "customer_name": str(row["customer_name"]).strip(), "amount": Decimal(row["amount"]), # finansal — string'den "quantity": int(row["quantity"]), "is_paid": row["is_paid"].lower() == "true", # custom bool parse "ordered_at": datetime.strptime( row["ordered_at"], "%Y-%m-%d %H:%M:%S" ), "tags": row["tags"].split(",") if row["tags"] else [], } # CSV oku ve parse et with open("orders.csv") as f: reader = csv.DictReader(f) orders = [parse_order_row(row) for row in reader] print(orders[0])
CSV her field'ı string olarak veriyor. Sen anlamlı tiplere cast ediyorsun. Bu pattern her veri pipeline'ının başında.
Hatalı cast handling#
def safe_int(value, default=0): """Cast başarısız ise default döner.""" try: return int(value) except (ValueError, TypeError): return default print(safe_int("42")) # 42 print(safe_int("abc")) # 0 print(safe_int(None)) # 0 print(safe_int("3.14")) # 0 (int direct float string'i parse etmez) def safe_decimal(value): """Para için temiz cast.""" if value is None or value == "": return None if isinstance(value, str): value = value.strip().replace(",", ".") # Türkçe ondalık virgül try: return Decimal(str(value)) except (ValueError, TypeError): return None
Production kodda her cast ile saracaksın — özellikle external veriden geldi ise.
try/exceptModern alternatif: Pydantic ile otomatik cast#
Pydantic (v2 — 2024+) data validation ve cast'ı otomatize ediyor:
from pydantic import BaseModel, Field from datetime import datetime from decimal import Decimal from typing import Optional class Order(BaseModel): id: int customer_name: str amount: Decimal quantity: int = Field(gt=0) # > 0 validation is_paid: bool ordered_at: datetime tags: list[str] = [] # String'leri direkt cast ediyor order = Order( id="42", # str → int customer_name="Şükrü", amount="19.99", # str → Decimal quantity="2", # str → int is_paid="true", # str → bool ordered_at="2026-01-15T10:30:00", # ISO string → datetime tags=["pro", "vip"], ) print(order) # Order(id=42, customer_name='Şükrü', amount=Decimal('19.99'), # quantity=2, is_paid=True, ordered_at=datetime(2026, 1, 15, 10, 30), # tags=['pro', 'vip']) print(order.amount + Decimal('5')) # Decimal('24.99') # Hata durumu try: bad = Order( id="not-a-number", customer_name="X", amount="abc", quantity=-1, is_paid="maybe", ordered_at="invalid-date", ) except Exception as e: print(e) # Detaylı validation hata mesajı
Pydantic FastAPI'nin temeli; modern Python web/API development'ta vazgeçilmez. ile request body'sini otomatik cast + validate ediyor.
Order(**request.json)dataclass + manual cast#
Pydantic kurmadan dataclass'la basit cast:
from dataclasses import dataclass from typing import Any @dataclass class User: id: int name: str age: int def __post_init__(self): self.id = int(self.id) self.age = int(self.age) self.name = str(self.name).strip() u = User(id="42", name=" Ali ", age="30") print(u) # User(id=42, name='Ali', age=30)
__post_init__NumPy/pandas dtype cast#
Veri analizi/AI'da farklı tipler arası geçiş çok yaygın:
import numpy as np arr = np.array([1, 2, 3, 4, 5]) print(arr.dtype) # int64 # astype — explicit dtype dönüşümü arr_float = arr.astype(np.float32) print(arr_float.dtype) # float32 print(arr_float) # [1., 2., 3., 4., 5.] # Truncation (int'e cast) arr_f = np.array([1.7, 2.3, -1.5]) arr_int = arr_f.astype(np.int32) print(arr_int) # [1, 2, -1] (truncate, not round) # Bool array → int mask = np.array([True, False, True]) print(mask.astype(int)) # [1, 0, 1] # String'leri int'e str_arr = np.array(["1", "2", "3"]) print(str_arr.astype(int)) # [1, 2, 3] import pandas as pd df = pd.DataFrame({ "id": ["1", "2", "3"], "amount": ["19.99", "5.00", "100.50"], "active": ["true", "false", "true"], }) # Bulk cast df["id"] = df["id"].astype(int) df["amount"] = df["amount"].astype(float) df["active"] = df["active"].map({"true": True, "false": False}) print(df.dtypes) # id int64 # amount float64 # active bool # Numeric columns df2 = pd.DataFrame({"x": [1, 2, 3], "y": [4.0, 5.0, 6.0]}) df2 = df2.astype({"x": float, "y": int}) print(df2.dtypes) # x float64 # y int64
astypepd.to_numericpd.to_datetimeYaygın tuzaklar#
1. int("3.14") hatası#
int("3.14")# 🚫 int("3.14") # ValueError # ✅ int(float("3.14")) # 3 (truncation)
2. bool("False") truthy#
bool("False")# 🚫 Beklenen False ama: print(bool("False")) # True (string boş değil) print(bool("0")) # True (string boş değil) # ✅ Custom parse def parse_bool(s): return s.strip().lower() in ("true", "yes", "1", "on") print(parse_bool("False")) # False print(parse_bool("Yes")) # True
3. Decimal(0.1) precision sızıntısı#
Decimal(0.1)# 🚫 Decimal(0.1) # 0.1000000000000000055... # ✅ Decimal('0.1') # 0.1
4. list("abc") ile list(["abc"]) farkı#
list("abc")list(["abc"])list("abc") # ['a', 'b', 'c'] (string iterate) list(["abc"]) # ['abc'] (single-element list)
5. set ile mutable elemanlar#
set# 🚫 — list mutable, hashable değil set([[1, 2], [3, 4]]) # TypeError: unhashable type: 'list' # ✅ set([(1, 2), (3, 4)]) # {(1, 2), (3, 4)} (tuple immutable) set(map(tuple, [[1, 2], [3, 4]])) # aynı
6. dict constructor kafa karışıklığı#
dict# Yöntem 1: keyword args dict(a=1, b=2) # {'a': 1, 'b': 2} # Yöntem 2: list of pairs dict([("a", 1), ("b", 2)]) # aynı # 🚫 ikisini karıştırma dict({"a": 1}) # {'a': 1} (existing dict copy) dict({"a": 1}, b=2) # {'a': 1, 'b': 2} (kwargs ekleme) # Şu hata # dict("abc") # ValueError (string is not 2-tuple iterable)
7. float('inf') ve float('nan') hassasiyet#
float('inf')float('nan')import math inf = float('inf') nan = float('nan') print(int(inf)) # OverflowError print(int(nan)) # ValueError
inf ve nan int'e cast edilemiyor — explicit kontrol et.
Bu derste neler kazandın?#
✓ Implicit vs explicit dönüşüm farkı.
✓ derinlemesine — base parametresi, string parse, magic methods (int, index).
int()✓ — scientific notation, inf/nan, Decimal/Fraction etkileşimi.
float()✓ — vs , ile özel format.
str()__str____repr____format__✓ — truthiness, custom .
bool()__bool__✓ Collection cast'ları: list, tuple, set, frozenset, dict, dict.fromkeys.
✓ bytes/bytearray — encode/decode, fromhex, custom .
__bytes__✓ Pratik 1: CSV → typed dict pipeline.
✓ Pratik 2: , defensive cast.
safe_intsafe_decimal✓ Pydantic — modern auto-cast + validation.
✓ NumPy/pandas dtype — , type-coerce.
astype✓ 7 yaygın tuzak — int/float string, bool string, Decimal float, list string, set mutable, dict kwargs, inf/nan.
Sıradaki ders: , , — Modül 2'nin son dersi. Identity vs equality, Python'un small int caching, string interning, weakref önizleme. Tüm modül boyunca arka planda olan kavramları derinleştiriyoruz.
id()is==Sık Sorulan Sorular
v2 (2023) Rust-tabanlı parser kullanıyor — v1'den 5-50x hızlı. v2 default'ta strict mode (tip uyumsuzluğunda hata), v1 daha gevşek. v2'de `BaseModel.dict()` yerine `.model_dump()`, `parse_obj` yerine `model_validate` — API değişti. Yeni proje v2 ile başla; mevcut v1 kodunu migration guide ile geçir. v1 hala destekleniyor (bug fixes) ama yeni feature v2'ye gidiyor.
Yorumlar & Soru-Cevap
(0)Yorum yazmak için giriş yap.
Yorumlar yükleniyor...
İlgili İçerikler
Modül 1: Giriş ve Kurulum
Python Nedir, Neden Bu Kadar Popüler?
Öğrenmeye BaşlaModül 1: Giriş ve Kurulum
Python Sürümlerinin Tarihi: 2'den 3.14'e, AI Winter'lardan 'No-GIL' Devrimine
Öğrenmeye BaşlaModül 1: Giriş ve Kurulum