Ana içeriğe geç
Kesit Python
İleri · Yapay Zekâ

Yapay zekâ asistanıyla Python yazmak

Claude, ChatGPT ve Copilot gibi asistanlardan bağlamlı, örnekli ve kısıtlı istemlerle doğru kod alır; üretilen kodu testle doğrular, uydurma API, eski sözdizimi, sessiz mantık hatası ve güvenlik açıklarını yakalar; yapay zekâ çıktısını (JSON) ayrıştırıp doğrularsın.

Uygulamada aç, 29 alıştırmayı çözÜcretsiz, hesap gerekmez, kurulum yok.

Bu sayfa dersin okuma sürümüdür. Metin bir kutuyu çalıştırmanı ya da adıma geçmeni söylüyorsa dersi uygulamada aç.

Neden önemli?

Bugün profesyonel geliştiricilerin büyük kısmı günlük işinde bir yapay zekâ asistanı kullanıyor: sohbet arayüzünde Claude ya da ChatGPT, editörün içinde GitHub Copilot ya da Cursor, terminalde Claude Code gibi ajanlar. Bu araçlar iskelet kodu, test, belge ve yeniden düzenlemeyi dakikalara indirir. Ama asistan emin görünen bir dille yanılabilir: var olmayan bir fonksiyonu çağırabilir, iki yıl önce kaldırılmış bir API kullanabilir, testsiz bırakıldığında yalnızca "mutlu yol"u çalıştıran kod yazabilir. Bu derste asistanı hızlandırıcı olarak kullanmayı, ama son sözü her zaman testlere ve senin muhakemene bırakmayı öğreneceksin. LLM API dersinde modeli kendi kodundan çağırmayı görüyorsun; burada asistanı bir çalışma arkadaşı olarak kullanmaya odaklanıyoruz.

Araç türüÖrnekEn iyi olduğu işDikkat
Sohbet asistanıClaude, ChatGPT, GeminiTasarım tartışması, açıklama, fonksiyon/test yazma, hata ayıklama (debugging)Projenin tamamını görmez; bağlamı sen verirsin
Editör içi tamamlamaGitHub Copilot, CursorSatır/blok tamamlama, tekrarlayan kalıplarHızlı kabul alışkanlığı; okumadan Tab'a basma
Kodlama ajanıClaude Code ve benzerleriÇok dosyalı değişiklik, test çalıştırıp düzeltme döngüsüDeğişikliği diff olarak incele, yetkileri sınırla

İyi istemin anatomisi

Asistan senin projeni, veri biçimini, Python sürümünü ve kurum kurallarını bilmez. Ne kadar belirsiz sorarsan o kadar "ortalama internet kodu" alırsın. İyi bir kodlama istemi (prompt) şu parçaları içerir:

ParçaÖrnek
Rol ve bağlam"Anadolu Market'in sipariş servisinde çalışıyorum; Python 3.12, yalnız standart kütüphane."
Görev"Siparişleri şehre göre gruplayıp ciroyu hesaplayan fonksiyon yaz."
Girdi-çıktı örneği"Girdi: [{"sehir": "İzmir", "tutar": 100}] → Çıktı: {"İzmir": 100.0}"
Kısıtlar"Para için Decimal kullan, tip ipuçları (type hint) ekle, harici paket yok, iptal siparişleri sayma."
Kenar durumlar"Boş liste, eksik şehir alanı, negatif tutar ne olmalı?"
Çıktı biçimi"Önce fonksiyonu, sonra pytest testlerini ayrı kod bloklarında ver; açıklama 3 maddeyi geçmesin."
ZAYIF:  python ile ciro hesaplama kodu yaz

GÜÇLÜ:  Python 3.12, yalnız standart kütüphane.
        Görev: sehir_ciro(siparisler: list[dict]) -> dict[str, Decimal]
        Her sipariş {"sehir": str, "tutar": str, "durum": str}; tutar metin ("149.90").
        Kurallar: durum "iptal" olanları atla; şehir yoksa "Bilinmiyor".
        Örnek: [{"sehir":"İzmir","tutar":"100.50","durum":"teslim"}] -> {"İzmir": Decimal("100.50")}
        Önce bu kurallar için 5 pytest testi yaz, sonra testleri geçen fonksiyonu yaz.
        Varsayım yapman gerekirse kodun üstünde madde olarak yaz.
Adım adım isteBüyük bir görevi tek istemde isteme. Önce "tasarımı madde madde öner, kod yazma" de; tasarımı onayla; sonra parça parça kodu iste. Hata aldığında tam hata mesajını ve ilgili kodu yapıştır, "neden olduğunu açıkla, sonra düzelt" de. Asistanın önce test yazmasını istemek (test-first) çoğu zaman en verimli yoldur.

Doğrulama döngüsü: güven ama test et

Asistanın kodunu üç adımda doğrularsın: oku (anlamadığın satırı kabul etme), çalıştır (gerçek örnekle), test et (kenar durumlarla). Aşağıda bir asistanın yazdığı, ilk bakışta doğru görünen bir fonksiyon var; küçük bir test kümesi hatayı hemen ortaya çıkarıyor.

def ortalama_sepet(tutarlar):
    """Yapay zekâ çıktısı: sepet tutarlarının ortalaması."""
    return sum(tutarlar) / len(tutarlar)

denemeler = [[100, 200, 300], [49.9], []]
for girdi in denemeler:
    try:
        print(girdi, "->", ortalama_sepet(girdi))
    except Exception as e:
        print(girdi, "-> HATA:", type(e).__name__, e)

Boş liste, "mutlu yol" testinde hiç akla gelmeyen ama üretimde ilk gün karşına çıkacak durumdur. Asistana "bu fonksiyonun kenar durumlarını listele ve her biri için test yaz" demek, en ucuz kalite yatırımıdır. Testleri sen de okumalısın: asistan bazen yanlış kodu "doğrulayan" yanlış test yazar.

Yapay zekânın tipik hataları

Hata türüÖrnekNasıl yakalarsın?
Uydurma API (halüsinasyon)liste.push(x), metin.contains("a"), math.clampÇalıştır; resmi belgeye bak; hasattr/help()
Eski sürüm kodufrom collections import Mapping (3.10'da kaldırıldı), pandas df.append (2.0'da kaldırıldı)Sürümünü istemde belirt; uyarıları (DeprecationWarning) oku
Sessiz mantık hatasıDeğiştirilebilir varsayılan argüman, sayfalamada bir eksik/fazla, metin olarak sayı sıralama, float ile paraKenar durum testleri, özellik (property) testleri
Güvenlik açığıf-string ile SQL, eval, shell=True, random ile tokenWeb güvenliği kontrol listesi, bandit
Aşırı geniş hata yakalamaexcept Exception: return NoneHangi hatanın neden yakalandığını sor
Gereksiz bağımlılık / karmaşıklıkTek satırlık iş için paket önermek"Yalnız standart kütüphane" kısıtı

Uydurma API şüphesinde kendi ortamında hızlıca kontrol et:

import builtins, importlib

def api_var_mi(yol: str) -> bool:
    modul_adi, *oznitelikler = yol.split(".")
    try:
        nesne = importlib.import_module(modul_adi)
    except ImportError:
        if not hasattr(builtins, modul_adi):
            return False
        nesne = getattr(builtins, modul_adi)
    for ad in oznitelikler:
        if not hasattr(nesne, ad):
            return False
        nesne = getattr(nesne, ad)
    return True

for yol in ["str.removeprefix", "str.contains", "list.push", "math.isclose", "math.clamp", "json.loads"]:
    print(f"{yol:18} {api_var_mi(yol)}")

Kod inceleme kontrol listesi

  1. Anlıyor muyum? Her satırı açıklayabiliyor musun? Açıklayamıyorsan asistana sor ya da yeniden yazdır.
  2. Çalışıyor mu? Gerçek bir örnekle çalıştır; hatasız çalışması doğru olduğu anlamına gelmez.
  3. Testi var mı? Mutlu yol + boş girdi + sınır değerler + hatalı girdi.
  4. API gerçek mi, güncel mi? Kullandığın Python ve paket sürümüyle uyumlu mu?
  5. Güvenli mi? SQL parametreli mi, kullanıcı girdisi doğrulanıyor mu, gizli bilgi koda gömülü mü?
  6. Projeye uyuyor mu? Adlandırma, hata yönetimi, loglama ve klasör yapısı ekip standardına uygun mu?
  7. Lisans sorunu var mı? Uzun, tanıdık görünen bir blok bilinen bir projeden kopya olabilir.

Yeniden düzenleme ve belge yazdırma

Asistanlar çalışan ama dağınık kodu toparlamada çok iyidir: "davranışı değiştirmeden fonksiyonu küçük parçalara böl, tip ipuçları ve docstring ekle" de. Kural: önce test, sonra yeniden düzenleme. Testler, asistanın davranışı sessizce değiştirmediğini kanıtlar. Docstring'e örnek koyarsan doctest ile belge de test olur:

import doctest
from decimal import Decimal

def kdv_ekle(tutar: Decimal, oran: Decimal = Decimal("0.20")) -> Decimal:
    """Tutara KDV ekler ve kuruşa yuvarlar.

    >>> kdv_ekle(Decimal("100"))
    Decimal('120.00')
    >>> kdv_ekle(Decimal("49.90"), Decimal("0.10"))
    Decimal('54.89')
    """
    return (tutar * (1 + oran)).quantize(Decimal("0.01"))

runner = doctest.DocTestRunner()
for test in doctest.DocTestFinder().find(kdv_ekle, "kdv_ekle", globs={"Decimal": Decimal, "kdv_ekle": kdv_ekle}):
    runner.run(test)
print("doctest:", runner.tries, "örnek,", runner.failures, "hata")

Yapay zekâ çıktısını programla işlemek

Asistanı bir boru hattında (pipeline) kullandığında (ör. müşteri yorumlarını sınıflandırma) yanıtı insan değil kod okur. Modelden JSON iste, ama gelen metnin her zaman temiz JSON olacağını varsayma: başında açıklama cümlesi, etrafında üç ters tırnaklı kod çiti, sonunda fazladan virgül olabilir. Önce ayıkla, sonra json.loads, sonra şemaya göre doğrula; doğrulama başarısızsa hatayı modele geri gönderip yeniden dene.

import json, re

CIT = chr(96) * 3   # üç ters tırnak
yanit = ("Tabii, sonuç aşağıda:\n" + CIT + "json\n"
         '{"yorum_id": 17, "duygu": "olumsuz", "konu": "kargo", "guven": 0.92}\n' + CIT)

eslesme = re.search(CIT + r"(?:json)?\s*(\{.*?\})\s*" + CIT, yanit, re.S)
veri = json.loads(eslesme.group(1) if eslesme else yanit)

hatalar = []
if veri.get("duygu") not in {"olumlu", "olumsuz", "notr"}:
    hatalar.append("duygu geçersiz")
if not (isinstance(veri.get("guven"), (int, float)) and 0 <= veri["guven"] <= 1):
    hatalar.append("guven 0-1 aralığında olmalı")
print(veri)
print("hatalar:", hatalar)

Pydantic dersinde gördüğün modellerle bu doğrulamayı tek satıra indirebilirsin; birçok LLM API'si de "yapılandırılmış çıktı" (structured output) ya da araç çağrısı (tool use) özelliğiyle şemaya uyan JSON üretmeyi destekler.

Gizli bilgi, kişisel veri ve lisans

Asistana yapıştırmadan önce düşünAPI anahtarı, veritabanı parolası, müşteri adı, TC kimlik numarası, kart bilgisi, iç sunucu adresleri asla istem içine girmez. Kurumunun onaylı (kurumsal sözleşmeli, veriyi eğitimde kullanmayan) aracını kullan; hata ayıklama için gerçek veri yerine maskelenmiş ya da sahte örnek ver. Yanlışlıkla bir anahtar paylaştıysan anahtarı hemen iptal edip yenile.

Lisans ve telif tarafında: üretilen kod bazen açık kaynak bir projeden neredeyse birebir parça içerebilir; GPL gibi "copyleft" lisanslı kod, kapalı kaynak ürününe girerse hukuki risk doğurur. Uzun, özgün görünen blokları kaynak aramasıyla kontrol et, editör araçlarının "kamuya açık kodla eşleşmeyi engelle" ayarlarını aç ve kurumunun yapay zekâ kullanım politikasına uy. Yazdığın koddan, kim üretmiş olursa olsun, sen sorumlusun.

Gerçek işteEkiplerde yapay zekâ ile yazılmış kod, diğer kodlarla aynı kod incelemesinden (code review) geçer; "yapay zekâ yazdı" bir mazeret değildir. Verimli ekipler asistanı en çok test yazdırma, eski kodu anlama ("bu modül ne yapıyor, akışı madde madde anlat"), hata mesajı yorumlama, belge ve commit mesajı taslağı için kullanır. Mülakatlarda da artık "asistanın önerdiği bu kodda ne yanlış?" türü sorular soruluyor: bu dersteki Hata avı alıştırmaları tam olarak bu beceriyi çalıştırıyor.
Derinleş

Derinleş: ajanlı kodlama iş akışı

Sohbet asistanı sana kod parçası verir; kodlama ajanı (coding agent) ise depoyu okur, dosyaları düzenler, testleri ve komutları çalıştırır, çıktıya bakıp kendini düzeltir. Claude Code (terminal ve IDE), Cursor'ın ajan modu ve GitHub'daki ajanlar bu sınıftadır. Güç arttıkça senin rolün "kodu yazan"dan görevi tanımlayan, sınırları çizen ve sonucu inceleyen kişiye kayar. Bu bölüm o rolü anlatıyor.

Döngü: keşfet → planla → uygula → doğrula

  1. Keşfet: Ajandan önce kodu okumasını iste ("ilgili dosyaları bul, henüz değiştirme"). Yanlış varsayımlar en ucuz bu aşamada yakalanır.
  2. Planla: Değişikliği adımlara bölmesini ve planı sana göstermesini iste. Planı onayla ya da düzelt.
  3. Uygula: Küçük adımlarla; her adım ayrı commit. Büyük tek seferlik değişiklik incelenemez.
  4. Doğrula: Testler, linter, tip denetimi ajanın kendi çalıştırabileceği komutlar olmalı. "Bitti" demesi değil, testlerin yeşil olması ölçüttür.

İyi görev tanımı bir iş biletine benzer: amaç, kapsam (hangi dosyalar/modüller), kapsam dışı, kabul ölçütleri (hangi testler geçmeli), kısıtlar (yeni bağımlılık yok, genel API değişmez). Büyük işi bağımsız alt görevlere böl: "CSV içe aktarmayı yeniden yaz" yerine önce "mevcut davranışı belgeleyen testleri yaz", sonra "ayrıştırıcıyı ayır", sonra "hata raporlamayı ekle".

gorevler = {
    "testleri_yaz": [],
    "ayristiriciyi_ayir": ["testleri_yaz"],
    "hata_raporu": ["ayristiriciyi_ayir"],
    "belgeleri_guncelle": ["ayristiriciyi_ayir"],
}
from graphlib import TopologicalSorter
print(list(TopologicalSorter(gorevler).static_order()))

Kurallar dosyası: projenin hafızası

Ajan her oturuma sıfır bağlamla başlar. Projenin kökündeki kurallar dosyası (Claude Code için CLAUDE.md, Cursor için .cursor/rules, birçok araç için AGENTS.md) her oturumda otomatik okunur. İçine yalnız kalıcı ve doğrulanabilir bilgi koy: nasıl kurulur, nasıl test edilir, kod stili, dokunulmayacak yerler. Uzun ve belirsiz dosya ("temiz kod yaz") işe yaramaz; kısa ve komut odaklı olsun.

# CLAUDE.md — Anadolu Market sipariş servisi

## Komutlar
- Kurulum: uv sync
- Test: uv run pytest -q   (her değişiklikten sonra çalıştır)
- Lint/biçim: uv run ruff check . && uv run ruff format --check .

## Kurallar
- Python 3.12, tip ipuçları zorunlu; para tutarları Decimal.
- Yeni bağımlılık eklemeden önce sor.
- migrations/ ve config/prod.yaml dosyalarını DEĞİŞTİRME.
- Veritabanı sorgularında f-string YOK; parametre kullan.

## Mimari
- api/ (FastAPI uç noktaları) → servis/ (iş kuralları) → depo/ (SQL). Katman atlama yok.

MCP ile araç bağlamak

Model Context Protocol (MCP), ajanın dış araçlara (veritabanı, hata takip sistemi, belge deposu, tarayıcı) standart bir arayüzle bağlanmasını sağlar. Bir MCP sunucusu araçlarını adı, açıklaması ve JSON şemalı girdileriyle ilan eder; ajan gerektiğinde çağırır. LLM API dersindeki araç çağırma döngüsünün standartlaşmış hâlidir. Güvenlik kuralı: ajana yalnız gereken araçları ve en az yetkiyi ver (salt okunur veritabanı kullanıcısı, test ortamı anahtarı). Araçtan gelen metin de güvenilmeyen girdidir; istem enjeksiyonu taşıyabilir.

// .mcp.json (proje kökü) — örnek yapı
{
  "mcpServers": {
    "market-db": {
      "command": "uvx",
      "args": ["mcp-server-sqlite", "--db-path", "./yerel_kopya.db"]
    }
  }
}

Ajan çıktısını PR olarak incelemek

Ajanın değişikliği bir dal (branch) ve çekme isteği (pull request) olarak gelmeli; ana dala doğrudan yazmamalı. İncelerken bir insanın kodunu incelerken baktığın her şeye ek olarak ajanlara özgü risklere bak:

KontrolNeden?
Diff kapsamı görevle uyumlu mu? İlgisiz dosya değişmiş mi?Ajanlar "bu arada" düzeltmeler yapar; incelenmemiş değişiklik riski.
Testler silinmiş, atlanmış (skip) ya da beklenen değer kodu tutacak şekilde değiştirilmiş mi?Testi geçirmenin en kolay yolu testi bozmaktır.
Yeni bağımlılık var mı? Paket gerçekten var mı, adı doğru mu?Uydurma ya da adı benzeyen kötü niyetli paketler (typosquatting).
Sır, anahtar, kişisel veri eklenmiş mi?Ajan log ya da örnek veriyi koda gömebilir.
Hata yutma: çıplak except, pass, sessiz NoneÇalışıyor gibi görünür, hatayı gizler.
CI yeşil mi ve sen de yerelde çalıştırdın mı?"Testler geçti" cümlesi kanıt değildir.
İzinlerAjana komut çalıştırma izni verirken izin listesini dar tut (test, lint, git diff). rm -rf, üretim veritabanı, git push --force, dağıtım komutları insan onayı istemeli. Mümkünse ajanı konteyner ya da ayrı bir çalışma ağacında (git worktree) çalıştır.
Gerçek işteEkipler ajanları en çok iyi tanımlı işlerde verimli buluyor: test yazma, bağımlılık güncelleme, tip ipucu ekleme, küçük hata düzeltmeleri, belge. Mimari kararlar ve belirsiz gereksinimler hâlâ insanın işi. Mülakatlarda "yapay zekâ araçlarını nasıl kullanıyorsun?" sorusuna iyi cevap, aracın adını değil doğrulama alışkanlığını anlatır: kurallar dosyası, küçük PR, test kanıtı, inceleme listesi.
Uzmanlaş

Projeye kalıcı bağlam ver

Kodlama ajanları proje kökündeki talimat dosyalarını (ör. Claude Code için CLAUDE.md) okuyabilir: Python sürümü, test komutu, kod stili, yasaklı kalıplar, klasör yapısı. Her istemde aynı bağlamı tekrar yazmak yerine bir kez yazarsın. Ajanın çalıştırabileceği komutları ve erişebileceği dosyaları sınırla; değişikliği her zaman diff olarak incele.

Testi sözleşme olarak kullan

Önce kendi yazdığın (ya da okuyup onayladığın) testler, sonra "bu testleri geçen kodu yaz" istemi: buna yapay zekâ ile TDD diyebilirsin. Testler sözleşmedir; asistan kodu değiştirdikçe testler korur. Testin de yanlış olabileceğini unutma: bilerek hatalı bir sürüme karşı testi çalıştırıp başarısız olduğunu görmek (mutasyon testi fikri), testin işe yaradığını kanıtlar.

Değerlendirme (eval) kümesi

Yapay zekâyı bir ürün özelliğinde (ör. yorum sınıflandırma) kullanıyorsan, beklenen çıktısı bilinen 50-200 örneklik bir değerlendirme kümesi kur; istem ya da model değiştiğinde doğruluğu yeniden ölç. Sezgiyle "daha iyi oldu" demek yerine sayıyla karar verirsin.

Alıştırmalara geç (29)