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 dakikalık okuma
Başlangıç📜 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: , , , — hepsi geçerli isim. Yani Python sana "şöyle yazmalısın" demiyor; topluluk diyor.
my_funcmyFuncMyFuncMYFUNCBu özgürlük teknik olarak iyi ama pratik olarak felaket olur:
- Aynı projede 3 farklı stil görmek kafayı karıştırır.
- Python kodunda çağrı yaparken yanlış geliyor — çünkü standart kütüphane
getUserDataile yazıyor.get_user_data - 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:
| Stil | Görünüm | Kullanı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__ | __init__ | Python'un kendisinin kullandığı magic methodlar — kendin oluşturmazsın |
Yaygın hata: camelCase Python'da yanlış#
camelCaseJava/JavaScript'ten gelenler yazma alışkanlığında olur. Python'da bu yanlış:
getUserData# 🚫 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 dosyası. Adı kısa, küçük harfli, snake_case olmalı.
.py# ✅ İ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 = içeren klasör. Modül kuralı uygula: kısa, küçük harf, snake_case.
__init__.pymy_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 (, , ) 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.
urllibjsonhtmlSabit (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 , classmethod'da .
selfclsclass 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 () ama linter'lar uyarır, takım reject eder. Bu kuralı bozma.
def increment(this):_ ve __ — alt çizgilerin gizli dili#
___Underscore'lar Python'da semantik anlam taşır:
Tek alt çizgi prefix: _name#
_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 *_İki alt çizgi prefix: __name (sınıfta)#
__nameName mangling tetikler. Sınıfta olursa Python otomatik 'e dönüştürür — alt sınıflarda override edilmesin diye.
__name_ClassName__nameclass 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)#
__double__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: , gibi dunder'lar dilin ayrılmış parçası.
__init____main__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, abbreviationsclass 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İ — PythonicMAX_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_has_can_should_# ✅ 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: , gibi sayısal değer için single OK.
user_countorder_total3. 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:
- (database)
db - (URL)
url - (identifier)
id - (HTTP)
http - (timezone)
tz - /
config(configuration)cfg
Ama yerine zaten 4 harf farkla daha okunaklı.
tztimezone5. 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:
-
Ekosistem İngilizce: Stack Overflow, GitHub, dokümantasyon, kitaplar — hepsi İngilizce. Türkçe değişken kullandığında o ekosisteme entegre olmuyorsun.
-
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.
-
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).İ -
AI asistanları İngilizce öğrenildi: Copilot, Claude, ChatGPT İngilizce kod örnekleriyle eğitildi.gördüklerinde tahmin iyi;
get_user()gördüklerinde fakir.kullanıcıGetir() -
İş 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 , , mantıklı çünkü kavram Türkçe. Ama yerine yine .
tc_kimlik_novergi_dairesikdv_oranıHesapla()calculate()Pratik kural: İngilizce yaz; domain-specific Türkçe kavramı snake_case ile İngilizleştir (, , ).
tc_idtax_officevat_rateSatı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#
ruffPEP 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 installBu 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(PascalCase)UserManager - →
MaxUsersmodül seviyesinde (constant convention)MAX_USERS - →
dbCon(snake_case + tam kelime)db_connection - ve
cnt→ tek attruserlist(count zaten len'de)users - ,
AddUser,GET_USER→isFull,add_user,get_user(snake_case)is_full - ,
U→ID,user(anlamlı, snake_case)user_id - explicit
get_userekledi (best practice)return None - →
u.IDu.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 (, ). (2) Bir 'aksiyon' mu (function, method) → snake_case verb (, ). (3) Bir 'kategori' mi (class) → PascalCase (). (4) Bir 'sabit' mi → UPPER_SNAKE (). (5) Boolean mu → snake_case prefix. (6) Internal use only → . (7) Magic method mu → (sadece Python'un kendisi).
usertotalget_usercalculate_totalUserManagerMAX_RETRYis_/has_/can_/should__leading_underscore__double_underscore__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 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.
intSık Sorulan Sorular
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...
İ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