List comprehension'lar bir kez kavrandığında, bir listeye ekleyen bir for döngüsü asla yazmayacaksınız. Bunlar sadece sözdizimsel şeker değil — niyeti açıkça belirtirler ve bytecode optimizasyonu sayesinde CPython'daki eşdeğer döngüden daha hızlı çalışırlar. Resmi Python öğreticisine göre, comprehension'lar mevcut dizilere veya diğer yinelenebilirlere dayalı listeler oluşturmak için özlü bir yol sağlar. Bu makale önce zihinsel modeli oluşturur, ardından her gerçek deseni kapsar: filtreleme, iç içe geçirme, dict ve set comprehension'ları ve bunun yerine düz bir for döngüsüne başvurmanız gereken tek durum.

Temel Desen

Bir list comprehension'ın anatomisi şudur: [ifade for öğe in yinelenebilir]. Üç kısım: çıktı ifadesi (her öğenin ne olduğu), döngü değişkeni ve yinelenebilir. Tanıdık bir döngüyle başlayıp onu yoğunlaştırın.

python
# Plain for loop — building a list of file sizes in KB
file_sizes_bytes = [1024, 204800, 51200, 3145728, 8192]

sizes_kb = []
for size in file_sizes_bytes:
    sizes_kb.append(size / 1024)

# print(sizes_kb)  →  [1.0, 200.0, 50.0, 3072.0, 8.0]

# Same result as a list comprehension — one line, same meaning
sizes_kb = [size / 1024 for size in file_sizes_bytes]

Comprehension neredeyse İngilizce gibi okunur: "file_sizes_bytes içindeki her size için size / 1024 ver." Bu netlik gerçek kazanımdır — bir okuyucunun ne inşa ettiğinizi anlamak için bir append çağrısını takip etmesi gerekmez.

python
# Another common pattern: deriving one list from another
usernames = ["alice", "bob", "carol"]

# Build a list of display names
display_names = [name.capitalize() for name in usernames]
# ['Alice', 'Bob', 'Carol']

# Or extract a single field from a list of dicts
users = [
    {"id": 1, "name": "Alice", "role": "admin"},
    {"id": 2, "name": "Bob",   "role": "viewer"},
    {"id": 3, "name": "Carol", "role": "editor"},
]

names = [user["name"] for user in users]
# ['Alice', 'Bob', 'Carol']

if ile Filtreleme

Sona bir koşul ekleyin ve yalnızca geçen öğeler çıktı listesine girer: [ifade for öğe in yinelenebilir if koşul]. Bu, for + if + append kombinasyonunun yerini alan desendir.

python
# Loop version — extract only active users
active_users = []
for user in users:
    if user["active"]:
        active_users.append(user["name"])

# Comprehension version — identical result
users = [
    {"name": "Alice", "active": True},
    {"name": "Bob",   "active": False},
    {"name": "Carol", "active": True},
    {"name": "Dave",  "active": False},
]

active_users = [user["name"] for user in users if user["active"]]
# ['Alice', 'Carol']
python
# Filtering a raw CSV row — drop blanks and whitespace-only values
raw_row = ["[email protected]", "", "  ", "editor", " "]

clean_row = [field.strip() for field in raw_row if field.strip()]
# ['[email protected]', 'editor']

# Filtering a list of log levels
log_lines = [
    "INFO  server started",
    "DEBUG loading config",
    "ERROR database timeout",
    "DEBUG query took 450ms",
    "ERROR disk space low",
]

errors = [line for line in log_lines if line.startswith("ERROR")]
# ['ERROR database timeout', 'ERROR disk space low']

Dizilerle Çalışma

Dizi işleme, comprehension'ların değerini kanıtladığı yerdir. Python'un zengin dizi metotları ve comprehension sözdiziminin kombinasyonu, dönüşüm pipeline'larını ara değişkenler olmadan okunabilir tutar.

python
# Strip whitespace from tags coming out of a form field
raw_tags = ["  python ", "data science", " machine-learning ", "API"]

tags = [tag.strip().lower() for tag in raw_tags]
# ['python', 'data science', 'machine-learning', 'api']

# Normalise email addresses from a signup CSV
raw_emails = ["[email protected]", "  [email protected]  ", "[email protected]"]

emails = [e.strip().lower() for e in raw_emails]
# ['[email protected]', '[email protected]', '[email protected]']

# Extract file extensions from a list of uploaded filenames
filenames = ["report.pdf", "avatar.PNG", "data.CSV", "archive.tar.gz", "notes.txt"]

extensions = [name.rsplit(".", 1)[-1].lower() for name in filenames if "." in name]
# ['pdf', 'png', 'csv', 'gz', 'txt']
İpucu: Kullanıcı girişini normalleştirirken, lowercase'den önce strip yapın — aksi takdirde " [email protected] " gibi bir değer içerikte .lower() kontrolünü geçer ama bir veritabanı aramasını veya JSON anahtar eşleşmesini bozacak baştaki boşlukları taşımaya devam eder.

Dict ve Set Comprehension'ları

Aynı fikir dict'lere ve set'lere de uzanır. Bir dict comprehension anahtar: değer çiftiyle süslü parantezler kullanır: {anahtar: değer for öğe in yinelenebilir}. Bir set comprehension iki noktayı kaldırır ve tekilleştirilmiş bir koleksiyon üretir: {ifade for öğe in yinelenebilir}.

python
# Invert a dict — swap keys and values
permissions = {"alice": "admin", "bob": "viewer", "carol": "editor"}

by_role = {role: name for name, role in permissions.items()}
# {'admin': 'alice', 'viewer': 'bob', 'editor': 'carol'}

# Build a fast lookup dict from a list of user records
users = [
    {"id": 101, "name": "Alice", "active": True},
    {"id": 102, "name": "Bob",   "active": False},
    {"id": 103, "name": "Carol", "active": True},
]

# O(1) lookups by ID — much faster than scanning the list every time
user_by_id = {user["id"]: user for user in users}
# {101: {...}, 102: {...}, 103: {...}}

# Access a user directly
user_by_id[102]["name"]  # 'Bob'
python
# Set comprehension — deduplicate a list of file extensions
uploads = ["report.pdf", "data.csv", "summary.pdf", "export.CSV", "notes.txt"]

unique_extensions = {name.rsplit(".", 1)[-1].lower() for name in uploads if "." in name}
# {'pdf', 'csv', 'txt'}  — order not guaranteed

Set'lerde bir uyarı: sıra korunmaz. Orijinal sırayı koruyarak bir listeyi tekilleştirmeniz gerekiyorsa, set comprehension yanlış araçtır — bunun yerine Python 3.7+'da dict'lerin ekleme sıralı davranışından yararlanan list(dict.fromkeys(öğeler))'i kullanın.

İç İçe Comprehension'lar

İç içe yapılar üzerinde yinelemek için comprehension'ları iç içe geçirebilirsiniz. En yaygın kullanım durumu, liste listesini düzleştirmektir — CSV parse'dan gelen bir matris, gruplandırılmış API yanıt sayfaları veya gruplandırılmış sorgu sonuçları.

python
# Flatten a 2D list (e.g. paginated API results)
pages = [
    [{"id": 1, "name": "Alice"}, {"id": 2, "name": "Bob"}],
    [{"id": 3, "name": "Carol"}],
    [{"id": 4, "name": "Dave"}, {"id": 5, "name": "Eve"}],
]

all_users = [user for page in pages for user in page]
# [{'id': 1, ...}, {'id': 2, ...}, {'id': 3, ...}, {'id': 4, ...}, {'id': 5, ...}]

# The order mirrors what nested for loops would produce:
# for page in pages:
#     for user in page:
#         all_users.append(user)

İç içe comprehension'ları soldan sağa okuyun — dış döngü önce, iç döngü ikinci gelir. Bu, iç içe for döngülerinin sırasıyla eşleşir.

python
# Two levels — fine and readable
matrix = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
flat = [cell for row in matrix for cell in row]
# [1, 2, 3, 4, 5, 6, 7, 8, 9]

# Three levels — stop here. Use a plain loop or a helper function.
# This is the point where readability dies:
cube = [[[1,2],[3,4]],[[5,6],[7,8]]]

# Don't do this:
flat3 = [val for layer in cube for row in layer for val in row]

# Do this instead:
flat3 = []
for layer in cube:
    for row in layer:
        flat3.extend(row)
Generator ifadeleri, köşeli parantezler yerine parantezlerle aynı sözdizimini kullanır: (user["id"] for user in users). Tembel değerlendirilirler — belleğe tam liste oluşturmak yerine öğeler birer birer üretilir. Yalnızca bir kez yinelemeniz gerektiğinde veya sonucu doğrudan sum(), max(), any() veya benzer fonksiyonlara geçirdiğinizde kullanın. Tam ayrıntılar için generator ifadeleri referansına bakın.

Comprehension İçinde if/else Üçlü İfadesi

Öğeleri kaldırmak yerine iki değerden birine dönüştürmeniz gerektiğinde — çıktı konumunda üçlü bir ifade kullanın. Konum önemlidir: üçlü ifade başa aittir, yinelenebilirin sonrasına değil.

python
# Correct: ternary is the output expression
users = [
    {"name": "Alice", "active": True},
    {"name": "Bob",   "active": False},
    {"name": "Carol", "active": True},
]

status = ["active" if user["active"] else "inactive" for user in users]
# ['active', 'inactive', 'active']

# Normalise a config value — replace None with a default
raw_config = ["/var/log", None, "/tmp", None, "/etc/app"]

paths = [path if path is not None else "/var/log/default" for path in raw_config]
# ['/var/log', '/var/log/default', '/tmp', '/var/log/default', '/etc/app']
python
# Common mistake — putting the ternary after the iterable (SyntaxError)
# status = ["active" for user in users if user["active"] else "inactive"]  # WRONG

# The trailing "if" is a filter — it drops non-matching items entirely.
# The ternary ("if ... else ...") in the output expression transforms all items.
# They serve different purposes. You can combine them:

# Keep only users, but show their status
status = ["active" if user["active"] else "inactive"
          for user in users
          if user["name"] != "Bob"]
# ['active', 'active']  — Bob was filtered out entirely

Bunun Yerine for Döngüsü Ne Zaman Kullanılır

List comprehension'lar liste oluşturmak içindir. Gerçekten yan etkiler çalıştırıyorsanız, bir for döngüsü kullanın — comprehension değil. Bu, stilin ötesinde önemlidir: sonucunu atan bir comprehension, kimsenin kullanmadığı bir liste oluşturarak belleği boşa harcar ve okuyucudan niyeti gizler.

python
# Bad — comprehension for side effects (writing to a file, printing, calling an API)
[print(f"Processing user {user['name']}") for user in users]   # don't do this
[requests.post("/api/notify", json=user) for user in users]    # definitely don't do this

# Good — plain for loop makes the intent obvious
for user in users:
    print(f"Processing user {user['name']}")

for user in users:
    requests.post("/api/notify", json=user)
python
# Bad — comprehension with logic complex enough to need comments or multiple steps
result = [
    user["name"].strip().lower()
    if user.get("active") and user.get("email_verified")
    else user["name"].strip().lower() + " (unverified)"
    for user in users
    if user.get("role") in ("admin", "editor") and user.get("last_login") is not None
]

# Good — break it out when the logic is this involved
result = []
for user in users:
    if user.get("role") not in ("admin", "editor"):
        continue
    if user.get("last_login") is None:
        continue
    name = user["name"].strip().lower()
    if not (user.get("active") and user.get("email_verified")):
        name += " (unverified)"
    result.append(name)
  • Comprehension kullanın mevcut bir yinelenebilirden net bir ifade ve isteğe bağlı bir filtre ile yeni bir liste oluşturduğunuzda.
  • for döngüsü kullanın yan etkiler çalıştırdığınızda — G/Ç, ağ çağrıları, yazdırma, dış durumu mutasyona uğratma.
  • for döngüsü kullanın dönüşüm mantığı anlaşılabilmesi için birden fazla satır, ara değişken veya yorum gerektirdiğinde.
  • Generator ifadesi kullanın yalnızca bir kez yinelemeniz veya doğrudan sum(), any(), max()'a geçirmeniz gerektiğinde — bellekte liste gerekmez.

Performans Notu

List comprehension'lar, CPython'da eşdeğer bir for + append döngüsünden anlamlı ölçüde daha hızlıdır. Nedeni bytecode'dur: bir comprehension, her yinelemede list.append'de özellik aramasını önleyen özel bir LIST_APPEND opcode'una derlenir. Python performans ipuçları wiki'si bunu kapsar ve fark, liste boyutuna bağlı olarak saf Python iş yükleri için tipik olarak %10–40'tır.

python
import timeit

data = list(range(100_000))

# for + append
def with_loop():
    result = []
    for x in data:
        result.append(x * 2)
    return result

# list comprehension
def with_comprehension():
    return [x * 2 for x in data]

# generator expression — no list built at all
def with_generator():
    return sum(x * 2 for x in data)

# Typical results on CPython 3.12:
# with_loop():          ~7.2 ms
# with_comprehension(): ~4.8 ms  (~33% faster)
# with_generator():     ~4.1 ms  (and uses O(1) memory vs O(n))

Somutlaştırılmış bir listeye ihtiyacınız yoksa — sonucu sum(), any(), max()'a geçiriyorsanız veya bir kez yineliyorsanız — bunun yerine bir generator ifadesi kullanın. Girdi boyutundan bağımsız olarak sabit bellek kullanır; bu, büyük CSV dışa aktarmalarını veya JSON yüklerini sıkı bir döngüde işlerken önemlidir.

Sonuç

List comprehension'lar, yaklaşık bir hafta garip hissettiren ve ardından vazgeçilmez hale gelen Python özelliklerinden biridir. Zihinsel model basittir: çıktı ifadesi, döngü değişkeni, yinelenebilir, isteğe bağlı filtre. Buna bağlı kalın ve okunabilir, deyimsel Python yazarsınız. Mantık karmaşıklaştığında, bu düz bir döngüye geri dönme sinyalidir — başarısızlık değil, iş için doğru araç.

Python'da JSON verileriyle çalışıyorsanız — API yanıtlarını değer listelerine dönüştürmek, kayıtlardan alanları çıkarmak, arama dict'leri oluşturmak — bu sitedeki araçlar öğrendiklerinizle iyi uyum sağlar. Onları işleyen comprehension'ı yazmadan önce JSON yüklerini incelemek ve güzel yazdırmak için JSON Formatter'ı, onu bir satır listesine ayrıştırmadan önce CSV verilerini doğrulamak için CSV Formatter'ı deneyin. Tam dil referansı için, Python'un list comprehension belgeleri ve PEP 202 (orijinal öneri) okunmaya değer.