Skip to content

PEP 8 İsimlendirme: Profesyonel Python Kodunun Görsel Disiplini

Bir Python kodu açtığında 30 saniye içinde 'profesyonel mi yoksa amatör mü' anlayabilirsin — isimlendirme. snake_case, PascalCase, UPPER_SNAKE, _private, __mangling. Bu derste her tipin nerede kullanıldığını, neden bu konvansiyon olduğunu, ruff ile otomatize etmeyi ve Türkçe değişken adı tartışmasını işliyoruz.

Şükrü Yusuf KAYA
18 min read
Beginner
PEP 8 İsimlendirme: Profesyonel Python Kodunun Görsel Disiplini
📜 PEP 8 — Python'un anayasası
Bir geliştiricinin profesyonelliğini en hızlı gösteren şey, kodundaki isimlendirme tutarlılığı. PEP 8 (Python Enhancement Proposal #8) Guido van Rossum ve Barry Warsaw'ın 2001'de yazdığı bir doküman — Python'un resmi stil rehberi. Bu derste kuralları öğrenmek dakikalar alır; refleks haline getirmek aylar. Ama refleks oturduğunda artık 'iyi kod yazma' bilinçli bir çaba değil, doğal bir hal alıyor.

Neden bir stil rehberine ihtiyaç var?#

Python sana özgürlük veriyor:
my_func
,
myFunc
,
MyFunc
,
MYFUNC
— hepsi geçerli isim. Yani Python sana "şöyle yazmalısın" demiyor; topluluk diyor.
Bu özgürlük teknik olarak iyi ama pratik olarak felaket olur:
  • Aynı projede 3 farklı stil görmek kafayı karıştırır.
  • getUserData
    Python kodunda çağrı yaparken yanlış geliyor — çünkü standart kütüphane
    get_user_data
    ile yazıyor.
  • Code review zaman kaybı: "ben snake_case kullanırım", "ben camelCase".
PEP 8 bu seçimi senin yerine yapıyor: Python topluluğunun ortak diline uy. Sonuç: stand kütüphane, popüler kütüphaneler, GitHub'daki repo'lar, senin projen — hepsi aynı görsel dilde konuşuyor.
"A foolish consistency is the hobgoblin of little minds." — PEP 8 girişi (Emerson'dan alıntı). Kuralları "şartsız" değil, "topluluk diline uyum" diye al.
Okuma için: pep8.org. Bu ders en kritik kısımları işliyor; ileri tartışmalar için orijinali oku.

Ana isimlendirme konvansiyonları#

Python'da 5 ana stil:
StilGörünümKullanım
snake_case
my_variable
Değişken, fonksiyon, method, modül, paket adı
PascalCase (UpperCamelCase)
MyClass
Sınıf adı, type alias
UPPER_SNAKE_CASE (SCREAMING_SNAKE)
MAX_RETRY
Sabit (constant)
_leading_underscore
_internal
Modülde private; "buna dışarıdan dokunma"
__double_leading
__mangled
Sınıf attribute'unda name mangling tetikler
__double__
(dunder)
__init__
Python'un kendisinin kullandığı magic methodlar — kendin oluşturmazsın

Yaygın hata:
camelCase
Python'da yanlış#

Java/JavaScript'ten gelenler
getUserData
yazma alışkanlığında olur. Python'da bu yanlış:
# 🚫 Java aksanı def getUserData(userId): db = getDatabase() return db.fetchUser(userId) # ✅ Pythonic def get_user_data(user_id): db = get_database() return db.fetch_user(user_id)
Bunu PEP 8 zorla yaptırmıyor; Python interpreter çalıştırır. Ama iş ilanlarında, code review'da, açık kaynak katkısında — Java aksanı kabul görmez. Disiplini başta öğrenmek seni rahatlatır.

Her tipin detaylı kuralları#

Modül adı#

Modül = bir
.py
dosyası. Adı kısa, küçük harfli, snake_case olmalı.
# ✅ İyi user_service.py data_loader.py http_client.py # 🚫 Kötü UserService.py # PascalCase modül adı (yanlış) user-service.py # tire (yanlış — Python tireyi minus operatörü olarak parse ediyor!) USER_SERVICE.py # büyük harf modül adı (kötü) userService.py # camelCase modül adı (yanlış)
Tire kullanırsan import hatası alırsın:
import user-service # SyntaxError!

Paket adı#

Paket =
__init__.py
içeren klasör. Modül kuralı uygula: kısa, küçük harf, snake_case.
my_app/ ├── __init__.py ├── core.py ├── utils.py └── auth/ ├── __init__.py ├── jwt.py └── session.py

Değişken adı#

snake_case. Anlamlı, ama gerektiğinden uzun değil.
# ✅ İyi user_count = 0 total_revenue = 1000.50 order_items = [] is_active = True has_permission = False # 🚫 Kötü n = 0 # tek harf — sadece çok dar scope'ta (ör. for i in range) userCount = 0 # camelCase UserCount = 0 # PascalCase (sınıf gibi gözükür) the_user_count_in_db = 0 # gereksiz uzun

Fonksiyon adı#

Değişken gibi: snake_case. Ama fonksiyonlar fiil ile başlamalı (action belirtir).
# ✅ İyi (fiil ile başlar) def calculate_total(items): ... def parse_json(text): ... def get_user(user_id): ... def validate_email(email): ... def is_authenticated(user): ... # bool dönüyorsa is_/has_/can_ prefix # 🚫 Kötü def total(items): ... # isim, fiil değil — bu fonksiyon mu, değişken mi? def Calculation(items): ... # PascalCase (sınıf gibi) def calc(items): ... # bilinmedik kısaltma def doStuff(items): ... # 'do' generic, ne yaptığı belirsiz

Sınıf adı#

PascalCase (her kelimenin ilk harfi büyük, ayraç yok).
# ✅ İyi class User: ... class HttpClient: ... class JsonParser: ... class DatabaseConnection: ... # 🚫 Kötü class user: ... # küçük harf (modül gibi gözükür) class HTTP_CLIENT: ... # SCREAMING_SNAKE (sabit gibi gözükür) class httpClient: ... # camelCase
İlginç durum: kısaltmalar genelde hep büyük değil, PascalCase.
# ✅ Pythonic — kısaltma da PascalCase'e dahil class HttpClient: ... class JsonParser: ... class XmlReader: ... class HtmlSanitizer: ... # 🚫 Java tarzı (yanlış) class HTTPClient: ... class JSONParser: ... class XMLReader: ...
Standart kütüphane (
urllib
,
json
,
html
) ve büyük kütüphaneler (django, flask) bu kurala uyuyor. Ama bazıları (NumPy, OpenCV) farklı yapıyor. Yenisini yazıyorsan PEP 8'e uy.

Sabit (constant)#

Modül seviyesinde tanımladığın değişmeyecek değerler: UPPER_SNAKE_CASE.
# ✅ İyi — modül başında, dosya seviyesi sabit MAX_RETRY = 3 DEFAULT_TIMEOUT = 30 API_BASE_URL = "https://api.example.com" LOG_LEVEL = "INFO" DATABASE_URL = "postgresql://..." # Bunlar fonksiyon çağrılarında "magic number" olmasın diye def fetch(url, retries=MAX_RETRY, timeout=DEFAULT_TIMEOUT): ...
Python'da gerçek immutable constant yok (her şey değiştirilebilir). UPPER_SNAKE sadece konvansiyon — "bu değiştirilmemeli" sinyali.

Method adı#

Sınıf method'ları snake_case (fonksiyon kuralı):
class User: def __init__(self, name): self.name = name def get_full_name(self): return f"{self.name}" def update_email(self, email): self.email = email def is_admin(self): return self.role == "admin"

Self ve cls#

Convention zorla: instance method'da
self
, classmethod'da
cls
.
class Counter: def __init__(self, initial=0): self.count = initial def increment(self): self.count += 1 @classmethod def from_zero(cls): return cls(initial=0)
Theoretically başka isim koyabilirsin (
def increment(this):
) ama linter'lar uyarır, takım reject eder. Bu kuralı bozma.

_
ve
__
— alt çizgilerin gizli dili#

Underscore'lar Python'da semantik anlam taşır:

Tek alt çizgi prefix:
_name
#

"Bu private — modülün/sınıfın iç implementasyonu, dışarıdan dokunma" sinyali. Konvansiyon, zorlama yok.
# my_module.py _internal_cache = {} # private _helper_function = ... # private def public_api(): # public ...
from my_module import *
yapanlar
_
'lı isimleri almayacak (bu yüzden anlamlı bir sinyal).

İki alt çizgi prefix:
__name
(sınıfta)#

Name mangling tetikler. Sınıfta
__name
olursa Python otomatik
_ClassName__name
'e dönüştürür — alt sınıflarda override edilmesin diye.
class A: def __init__(self): self.__secret = 42 class B(A): def __init__(self): super().__init__() self.__secret = "different" # B'nin kendi attribute'u, A'nın __secret'ını ezmiyor a = A() b = B() print(a._A__secret) # 42 (mangled) print(b._B__secret) # 'different' (mangled) print(b._A__secret) # 42 (B, A'dan inherit etti)
Pratik kullanımı nadir. Çoğu zaman tek
_
yeter.
__
'yi sadece inheritance hierarchy'sinde "ben özellikle alt sınıflar dokunmasın" istediğinde kullan.

__double__
dunder (magic methods)#

Python'un kendisinin kullandığı özel metodlar. Kendin yeni dunder yaratma — bu Python'a ayrılmış.
class MyClass: def __init__(self): ... # constructor def __repr__(self): ... # debug repr def __str__(self): ... # user-facing str def __len__(self): ... # len() fonksiyonu için def __eq__(self, other): ... # == operator için def __add__(self, other): ... # + operator için
Bunlar sıkça karşına çıkacak — Modül 11 (OOP II) detaylı işliyor. Şimdilik bilmen gereken:
__init__
,
__main__
gibi dunder'lar dilin ayrılmış parçası.

Tek alt çizgi olarak
_
#

Üç farklı bağlamda anlam taşır:
1. "Bu değeri umursamıyorum":
for _ in range(10): print("Hello") # 'i' lazım değil, _ kullan # Tuple unpacking x, _, z = (1, 2, 3)
2. REPL'de son sonuç:
>>> 5 + 3 8 >>> _ * 2 16
3. i18n / gettext:
from gettext import gettext as _ print(_("Hello")) # çevrilmiş "Merhaba"
Üç anlam aynı sembolde — bağlam belirler. Öğrendiğinde refleks olur.
python
# Yan yana good vs bad — kendine bir referans olarak tut
 
# 🚫 KÖTÜ — Java/JS aksanı, generic isimler, abbreviations
class userManager: # küçük harf class
MAX_USERS = 100 # OK ama class içinde mi?
def __init__(self):
self.userList = [] # camelCase
self.totalUsers = 0 # camelCase
self.tempData = None # 'temp' generic
def addUser(self, u): # camelCase + tek harf param
self.userList.append(u)
def getCnt(self): # 'getCnt' iki sebepten kötü
return len(self.userList)
 
 
# ✅ İYİ — Pythonic
MAX_USERS = 100 # modül seviyesi sabit
 
class UserManager: # PascalCase
def __init__(self):
self.users = [] # snake_case + anlamlı
self.total_count = 0
self._cache = None # private (underscore)
def add_user(self, user): # snake_case + anlamlı param
self.users.append(user)
def get_count(self): # snake_case + tam kelime
return len(self.users)
 
 
# Karşılaştır — birinin niyetini 1 saniyede anlıyorsun, diğerinde 10.
Aynı sınıfın iyi vs kötü versiyonları. PEP 8 disiplini görsel olarak farkı yaratıyor.

Anlamlı isim seçme — sezgisel rehber#

Stil kuralları kolay, anlamlı isim seçmek zor. İşte yıllar içinde gördüğüm rehberler:

1. Boolean variable'ları
is_
,
has_
,
can_
,
should_
ile başlat#

# ✅ is_active = True has_permission = False can_edit = True should_retry = True needs_validation = False # 🚫 active = True # active what? noun like permission = False # permission var mı yok mu? string mi?
Okur "if is_active:" gördüğünde "if some boolean check" diye yorumlar; netlik yüksek.

2. Liste'ler/koleksiyonlar çoğul#

# ✅ users = [user1, user2, user3] products = [] # 🚫 user_list = [...] # 'list' suffix'i gereksiz, dil zaten gösteriyor list_of_users = [...] # daha da kötü
İstisna:
user_count
,
order_total
gibi sayısal değer için single OK.

3. Tek harfli değişken sadece dar scope#

# ✅ for i in range(10): # i, j, k loop counter print(i) with open(f) as f: # bu farklı f'ler — kafa karıştırıcı, kullanma # Math/algorithm'da def euclidean_distance(a, b): return ((a[0]-b[0])**2 + (a[1]-b[1])**2) ** 0.5 # 🚫 def f(d, t, n): # f, d, t, n — hiçbiri okunmuyor return d * t / n # Daha iyi def calculate_speed(distance, time, divisor): return distance * time / divisor

4. Kısaltma gereksiz#

# ✅ user_count = 5 calculate_total = ... # 🚫 usr_cnt = 5 calc_ttl = ...
İstisna: yaygın kabul görmüş kısaltmalar:
  • db
    (database)
  • url
    (URL)
  • id
    (identifier)
  • http
    (HTTP)
  • tz
    (timezone)
  • config
    /
    cfg
    (configuration)
Ama
tz
yerine
timezone
zaten 4 harf farkla daha okunaklı.

5. Magic number'a anlam ver#

# 🚫 if status == 1: return result * 0.18 # ✅ ACTIVE_STATUS = 1 TURKEY_VAT_RATE = 0.18 if status == ACTIVE_STATUS: return result * TURKEY_VAT_RATE
Sabite isim verince: (a) okunmuş, (b) tek yerde tanımlı (DRY), (c) değiştirmek kolay.

6. Negatif boolean'dan kaç#

# 🚫 not_found = True is_invalid = False if not is_invalid: # double negative — anlamak zor ... # ✅ found = True is_valid = True if is_valid: # net ...
Pozitif ifade düşünmesi kolay.

Türkçe değişken adı kullanmalı mıyım?#

Sıkça gelen soru. Teknik olarak Python 3 her Unicode karakteri destekliyor:
çiçek_sayısı = 100 müşteri_listesi = [] def kullanıcı_getir(id): pass
Bu çalışıyor. Ama hiç kullanma. Sebepler:
  1. Ekosistem İngilizce: Stack Overflow, GitHub, dokümantasyon, kitaplar — hepsi İngilizce. Türkçe değişken kullandığında o ekosisteme entegre olmuyorsun.
  2. Takım çalışması zorlaşır: Sırf Türk takımda bile yıllar içinde yabancı geliştirici katılır, kod açık kaynak olur. Türkçe isimler engel olur.
  3. Türkçe karakterler bug yaratır: Eski Python sürümlerinde, bazı encoding bağlamlarında, IDE'lerde Türkçe karakter sorunlu.
    ş
    ,
    ğ
    ,
    ı
    /
    İ
    özellikle sorunlu (case conversion'da).
  4. AI asistanları İngilizce öğrenildi: Copilot, Claude, ChatGPT İngilizce kod örnekleriyle eğitildi.
    get_user()
    gördüklerinde tahmin iyi;
    kullanıcıGetir()
    gördüklerinde fakir.
  5. İş piyasası: Pratisyenler Türkçe isimli kod görüne hemen "amatör" damgası vurur. Şirket eline yeni başlayan junior bunu yapmaz.
İstisna: Domain'in Türkçe-spesifik olduğu yerler — TC kimlik numarası validation, vergi dairesi entegrasyonu, KDV hesaplama. Burada
tc_kimlik_no
,
vergi_dairesi
,
kdv_oranı
mantıklı çünkü kavram Türkçe. Ama
Hesapla()
yerine yine
calculate()
.
Pratik kural: İngilizce yaz; domain-specific Türkçe kavramı snake_case ile İngilizleştir (
tc_id
,
tax_office
,
vat_rate
).

Satır uzunluğu — PEP 8'in en tartışmalı kuralı#

PEP 8'in orijinal kuralı: 79 karakter. Sebebi tarihsel — eski terminallerin 80 sütunlu olması.
Modern dünyada bu kısıtlama gereksiz. Ekran wide, herkesin font'u modern. Topluluk önerileri:
  • Black (formatter) default'u: 88 karakter.
  • Django style guide: 119 karakter.
  • Google Python style: 80 karakter (klasik tutuyor).
  • Çoğu modern proje: 88-100 karakter.
# 88 karakter sınırında düzgün dur result = some_function(parameter_one, parameter_two, parameter_three, parameter_four) # Daha uzunsa kır result = some_function( parameter_one, parameter_two, parameter_three, parameter_four, ) # Backslash continuation EŞSİZ DURUMLARDA total = first_part + \ second_part + \ third_part # Daha iyi: parantez içinde implicit continuation total = (first_part + second_part + third_part)
Önerim: 88 karakter (black/ruff default'u). Bu sayı 88 sayısal değil; topluluk konsensüsü.
Editör'ünü 88 satır işareti gösterecek şekilde ayarla:
// VS Code settings.json { "editor.rulers": [88, 100] }
İki ruler: 88 (PEP 8/black ideal) ve 100 (gerekirse esnet) bir kılavuz.

PEP 8'i otomatize et —
ruff
#

PEP 8'i ezbere bilmek imkansız ve gereksiz. Modern Python ekosistemi bunu otomatize ediyor:

Ruff — modern champion#

Astral'ın Rust ile yazdığı ruff, hem linter (kuralları kontrol et) hem formatter (otomatik düzelt) — ve hızlı (10-100x flake8'den).
pip install ruff # Lint (sorunları göster) ruff check . # Otomatik düzelt ruff check --fix . # Format (PEP 8'e uygun yeniden yaz) ruff format .
VS Code extension yükle, settings.json'a:
{ "[python]": { "editor.defaultFormatter": "charliermarsh.ruff", "editor.formatOnSave": true, "editor.codeActionsOnSave": { "source.fixAll.ruff": "explicit", "source.organizeImports.ruff": "explicit" } } }
Şimdi her dosya kaydetmeyle:
  • PEP 8'e uygun format
  • Import'lar sıralı
  • Kullanılmayan import'lar silinir
  • Yaygın hata pattern'leri otomatik düzeltilir

pyproject.toml ile config#

[tool.ruff] line-length = 88 target-version = "py313" [tool.ruff.lint] select = [ "E", # pycodestyle errors "W", # pycodestyle warnings "F", # pyflakes "I", # isort "N", # pep8-naming ← isimlendirme! "UP", # pyupgrade "B", # flake8-bugbear "C4", # flake8-comprehensions "RUF", # ruff-specific ] ignore = [] [tool.ruff.lint.pep8-naming] classmethod-decorators = ["classmethod", "validator"]
Ruff "N" kuralları PEP 8 isimlendirmeyi denetler. Class adı snake_case ise — uyarır.

Pre-commit hook ile zorla#

# .pre-commit-config.yaml repos: - repo: https://github.com/astral-sh/ruff-pre-commit rev: v0.7.0 hooks: - id: ruff args: [--fix] - id: ruff-format
pre-commit install
— artık her commit öncesi otomatik kontrol. Hata varsa commit reddedilir.
Bu kombinasyon (ruff + pre-commit) "iyi kod yazma" disiplinini bireysel iradeden çıkarıp otomatik yapıyor. Modern Python projesi bunsuz olmaz.

Pratik: Aşağıdaki kodu PEP 8'e uygun hale getir#

Aşağıda kötü adlandırılmış bir kod var. Önce kendin düzelt, sonra benim önerimle karşılaştır.
class userManager: MaxUsers = 1000 def __init__(self, dbCon): self.DB = dbCon self.cnt = 0 self.userlist = [] def AddUser(self, U): if self.cnt >= self.MaxUsers: return False self.userlist.append(U) self.cnt += 1 return True def GET_USER(self, ID): for u in self.userlist: if u.ID == ID: return u def isFull(self): return self.cnt == self.MaxUsers
Düzeltme önerim:
MAX_USERS = 1000 # modül seviyesinde sabit, modülün başına class UserManager: def __init__(self, db_connection): self.db = db_connection self.users = [] # 'cnt' yerine listenin len'ini kullan def add_user(self, user): if len(self.users) >= MAX_USERS: return False self.users.append(user) return True def get_user(self, user_id): for user in self.users: if user.id == user_id: return user return None # explicit return None def is_full(self): return len(self.users) >= MAX_USERS
Değişiklikler:
  • userManager
    UserManager
    (PascalCase)
  • MaxUsers
    MAX_USERS
    modül seviyesinde (constant convention)
  • dbCon
    db_connection
    (snake_case + tam kelime)
  • cnt
    ve
    userlist
    → tek attr
    users
    (count zaten len'de)
  • AddUser
    ,
    GET_USER
    ,
    isFull
    add_user
    ,
    get_user
    ,
    is_full
    (snake_case)
  • U
    ,
    ID
    user
    ,
    user_id
    (anlamlı, snake_case)
  • get_user
    explicit
    return None
    ekledi (best practice)
  • u.ID
    u.id
Aynı kod, çok farklı görsel kalite. Bu fark PEP 8'in değeri.
🎯 Pratik özet — pratik bir karar matrisi
İsim seçerken hızlı kontrol: (1) Bir 'şey' mi (object, data) → snake_case noun (
user
,
total
). (2) Bir 'aksiyon' mu (function, method) → snake_case verb (
get_user
,
calculate_total
). (3) Bir 'kategori' mi (class) → PascalCase (
UserManager
). (4) Bir 'sabit' mi → UPPER_SNAKE (
MAX_RETRY
). (5) Boolean mu → snake_case
is_/has_/can_/should_
prefix. (6) Internal use only →
_leading_underscore
. (7) Magic method mu →
__double_underscore__
(sadece Python'un kendisi).

Bu derste neler kazandın?#

PEP 8'in neden var olduğu — bireysel özgürlük yerine topluluk dili.
5 ana isim stili: snake_case, PascalCase, UPPER_SNAKE, _private, __dunder.
Modül, paket, değişken, fonksiyon, sınıf, sabit, method, attribute için spesifik kurallar.
Self ve cls convention'ları.
Underscore'ların gizli dili — _, __, dunder, name mangling.
6 anlamlı isim seçim ipucu — boolean prefix, çoğul list, tek harf scope kuralı, kısaltma, magic number, negatif boolean.
Türkçe değişken tartışması — neden hayır, ne zaman istisna olabilir.
Satır uzunluğu — 88 modern standart.
Ruff + pre-commit ile otomatize. Disiplini iradeden çıkarmak.
Hands-on: Kötü kodu PEP 8'e dönüştürme egzersizi.
Sıradaki ders: Python'un
int
tipi. Diğer dillerde 32-bit veya 64-bit sınırlı; Python'da sınırsız. RSA encryption'ından factorial(1000)'e — neden Python "büyük sayı" işlerinde hâkim. Integer literals (binary, hex, octal), bit_length, performance karakteristikleri, small int caching.

Frequently Asked Questions

Linter uyarısının sebebini öğren — sonra düzelt. Yıllar içinde gördüğüm: 'görmezden gel' alışkanlığı kötü kod birikimine yol açıyor. Her uyarı bir bilgi taşıyor; %95'i gerçek iyileştirme. Modern toolchain (ruff + pre-commit + format-on-save) çoğunu otomatik düzeltiyor — sen düzeltmenle uğraşmıyorsun bile. Eğer **gerçekten** bir uyarıyı kabul edemezsen `# noqa: kural-kodu` yorumu ile satır bazında devre dışı bırak (gerekçeyi yorumla).

Yorumlar & Soru-Cevap

(0)
Yorum yazmak için giriş yap.
Yorumlar yükleniyor...

Related Content