Operator Precedence ve Assosiyatiflik: Parantezsiz Doğru Kod Yazma Sanatı
'a or b and c' nasıl evaluate edilir? '5 + 3 * 2' neden 11 değil 16? '~5 << 2' nedir? Python'un 18 seviyeli precedence tablosu ve sol/sağ assosiyatiflik kuralları. Bu derste: tam precedence tablosu, klasik tuzaklar, IDE warning'lerinin neden olduğu davranışları, ve 'parantez ne zaman gerek' net kararı.
Şükrü Yusuf KAYA
16 min read
Intermediate🎓 Bu konu sınav için değil — bug için
Hiçbir programcı operator precedence tablosunu ezbere bilmez. Ama tabloyu hiç tanımayan birinin kodunda subtle bug'lar oluyor: yazınca çalışıyor — beklenmedik. Bu derste bilmen gereken kritik kurallar ve ne zaman parantez kullanmak şart.
x & 1 == 0x & (1 == 0)Tam Precedence Tablosu (en yüksekten düşüğe)#
Python'un resmi tablosu — ezberlemen gerekmiyor, ama tanıdık olman lazım:
| Seviye | Operatör | İsim | Asosiyatiflik |
|---|---|---|---|
| 1 (en yüksek) | (...)[...]{...} | Parantez, indeks, koleksiyon | — |
| 2 | x[i]x[i:j]x(arg)x.attr | Subscription, slicing, call, attribute | sol |
| 3 | await x | Await | — |
| 4 | ** | Üs | sağ |
| 5 | +x-x~x | Unary | sağ |
| 6 | *@///% | Çarpma, matrix mul, bölme, floor, mod | sol |
| 7 | +- | Toplama, çıkarma | sol |
| 8 | <<>> | Shift | sol |
| 9 | & | Bitwise AND | sol |
| 10 | ^ | Bitwise XOR | sol |
| 11 | ` | ` | Bitwise OR |
| 12 | <<=>>===!=isin | Karşılaştırma, identity, membership | — (chain) |
| 13 | not x | Mantıksal NOT | sağ |
| 14 | and | Mantıksal AND | sol |
| 15 | or | Mantıksal OR | sol |
| 16 | if-else | Conditional expression (ternary) | sağ |
| 17 | lambda | Lambda | — |
| 18 (en düşük) | := | Walrus | — |
🎯 Anahtar gözlemler:
- Parantez en üstte — her zaman önce evaluate edilir.
- sağ assosiyatif:
**(NOT2**3**2 == 2**(3**2) == 2**9 == 512).(2**3)**2 == 64 - Aritmetik > shift > bitwise > comparison > logical.
- >
and.or - Comparison'lar chain edilebilir (Modül 2/Ders 10).
Klasik kurallar — okul matematiği#
Aritmetik kısmı zaten biliyorsun ama Python'a uyarlayalım:
# Çarpma > Toplama print(5 + 3 * 2) # 11 (NOT 16) print((5 + 3) * 2) # 16 # Üs > unary print(-2 ** 2) # -4 (NOT 4!) # Çünkü: -(2 ** 2) = -4 # Eğer (-2)**2 istiyorsan parantez gerek print((-2) ** 2) # 4 # ** sağ assosiyatif print(2 ** 3 ** 2) # 512 = 2**(3**2) = 2**9 print((2 ** 3) ** 2) # 64 # Bölme türleri aynı seviye, sol assosiyatif print(20 / 4 / 2) # 2.5 = (20 / 4) / 2 # Modulus aynı seviye print(10 % 6 % 4) # 0 = (10 % 6) % 4 = 4 % 4 = 0
-2 ** 2 == -4**- (2**2)Pratik: hız değil okunabilirlik için belirsiz olduğunda parantez kullan.
Aldatıcı durumlar — şüphe duyduğunda parantez#
1. Bit AND ile karşılaştırma#
# 🚫 Beklenmedik x = 5 if x & 1 == 1: print("Tek sayı") # Aslında: if x & (1 == 1): # = if x & True: # = if x & 1: → True (x bit 0 = 1) # Doğru çalışıyor gibi görünüyor — ama farklı sayılarda farklı sonuç y = 4 if y & 1 == 1: print("Tek sayı") # 0 (False) # Aslında: y & (1 == 1) = y & 1 = 0 — doğru # Bu örnekte tesadüfen doğru çalıştı — ama mantık yanlış # 'x & 1 == 1' diye düşünüyorsun, '(x & 1) == 1' demek # Python ise x & (1 == 1) yapıyor — '==' precedence > '&' # ✅ Açık if (x & 1) == 1: print("Tek")
==&|2. Walrus + comparison#
# 🚫 if (n := len(items) > 10): print(f"n = {n}") # Beklenen: n = len(items) # Aslında: n = (len(items) > 10) → True/False # n bool! # ✅ if (n := len(items)) > 10: print(f"n = {n}") # Burada n int olarak atanıyor, sonra > 10 karşılaştırılıyor
Walrus precedence'ı en düşük — parantez ile sınırla.
3. not ile in#
notin# 🚫 if not x in lst: ... # Çalışıyor ama anlam: (not x) in lst — yanlış mantıksal yapı # ✅ if x not in lst: ... # 'not in' tek operator (compound) # Gerçi bu örnekte ikisi de aynı sonuç çoğu zaman ama # semantic farklı — okuyana 'not in' daha açık
4. Conditional expression iç içe#
# 🚫 Okunmaz result = a if cond1 else b if cond2 else c # Aslında nasıl evaluate ediliyor: # result = a if cond1 else (b if cond2 else c) # Yani: cond1 ise a, değilse (cond2 ise b, değilse c) # ✅ Daha açık if cond1: result = a elif cond2: result = b else: result = c # Veya match match (cond1, cond2): case (True, _): result = a case (False, True): result = b case _: result = c
Nested ternary 2'den fazlaysa elif'e dönüş.
5. and/or öncelik sırası#
andor# 🚫 if x or y and z: ... # Aslında: if x or (y and z): # and > or olduğu için y and z önce # Eğer (x or y) and z istiyordun: if (x or y) and z: ...
andor6. = (atama) ve == karışmaz#
===Python'da syntax error verir — assignment ifade değil. C'de bu hata yok (bug kaynağı). Python bunu önlüyor. Walrus ifade ama bu da sınırlı yerlerde geçerli.
if x = 5:=Assosiyatiflik — sol mu sağ mı?#
İki aynı precedence'lı operatör arka arkaya geldiğinde hangi yön evaluate ediliyor:
# Sol assosiyatif (most operators) 20 - 5 - 3 # = (20 - 5) - 3 = 15 - 3 = 12 (NOT 20 - (5-3) = 18) 10 / 2 / 5 # = (10/2) / 5 = 5 / 5 = 1.0 # Sağ assosiyatif — özel: ** ve atama 2 ** 3 ** 2 # = 2 ** (3 ** 2) = 2 ** 9 = 512 a = b = c = 5 # = a = (b = (c = 5)) — sağ assosiyatif # Tüm değişkenler 5
**2^3^2 = 2^(3^2)Comparison chaining — özel davranış#
# 0 < x < 10 — chain (Modül 2/Ders 10) # Bu sol veya sağ değil; özel chaining kuralı a < b < c # = (a < b) and (b < c) — short-circuit a == b == c # = (a == b) and (b == c)
Comparison'lar normal binary op'lar gibi değil; her ikisi short-circuit'le and ile bağlanıyor.
Pratik kural: Parantez ne zaman?#
Stil rehberlerine baktığımızda iki yaklaşım var:
Minimal parantez (matematik tarzı)#
result = a + b * c # tabii ki çarpma önce mask = ~bits & 0xFF # bit op'lar normal sıra
Avantaj: kısa, matematiksel olarak doğal.
Dezavantaj: takım arkadaşın precedence'ı senin kadar bilmeyebilir.
Defensif parantez (savunmacı)#
result = a + (b * c) # gereksiz ama net mask = (~bits) & 0xFF # gereksiz ama net
Avantaj: şüphe yok.
Dezavantaj: dağınık kod.
Pratik orta yol — şu durumlarda mutlaka parantez:
- Bit op + comparison:
(x & 1) == 1 - Bit op + bit op (& ve |): — "a AND b ile or c" mu, "a AND (b or c)" mu? Belirsiz olmasın.
(a & b) | c - and/or karışık:
(x or y) and z - Walrus + comparison:
(n := len(x)) > 10 - Nested ternary: kullanma, elif yaz.
- Üs alma + minus: veya
(-2) ** 2— niyetin neyse.-(2 ** 2)
Diğer yerlerde Python'un default precedence'ı insan sezgisine yakın — parantez ekleyince clutter.
Debug aracı — ast modülü ile precedence görmek#
astOperator precedence'ı şüpheliysen Python sana parse tree'yi göstermeye razı:
import ast # Şu ifade nasıl parse oluyor? code = "x & 1 == 1" tree = ast.parse(code, mode="eval") print(ast.dump(tree, indent=2))
Çıktı:
Expression( body=BinOp( left=Name(id='x'), op=BitAnd(), right=Compare( left=Constant(value=1), ops=[Eq()], comparators=[Constant(value=1)] ) ) )
Yani: — beklediğin değil!
x & (1 == 1)ast.dumpDaha okunabilir: ast.unparse#
# Python 3.9+ import ast code = "x & 1 == 1" tree = ast.parse(code, mode="eval") # ast.unparse aynı ifadeyi yazıyor — ama parse tree'sine göre # Ama bu örnekte aynı görünüyor print(ast.unparse(tree)) # x & 1 == 1 # Daha karmaşık: code = "a or b and c" tree = ast.parse(code, mode="eval") print(ast.unparse(tree)) # a or b and c — Python original # Anlamı: a or (b and c) — and > or
ast modülü zaten Python parser'ının kendisi. Şüpheye düştüğünde ile gerçeği gör.
ast.parse + ast.dumpBu derste neler kazandın?#
✓ 18 seviyeli precedence tablosu — hangi operatör hangi sırada.
✓ Sağ assosiyatif olanlar: ve assignment.
**✓ precedence'ı bit op'lardan yüksek — bit + comparison'da parantez şart.
==✓ > — mantıksal karışımda parantez.
andor✓ klasik tuzağı (üs > unary).
-2 ** 2 = -4✓ Comparison chaining — özel kural, normal binary değil.
✓ 6 'mutlaka parantez' durumu.
✓ debugging aracı.
ast.parse + ast.dumpSıradaki ders: Type conversion (cast) — , , , , , , , , . Hangi dönüşüm hata atar, hangi otomatik (implicit), / / magic methods, ve NumPy/pandas dünyasında dtype dönüşümleri.
int()float()str()bool()list()tuple()set()dict()bytes()__int____float____str__Frequently Asked Questions
Hayır. **Bilmen gereken**: 5-6 yaygın kuralı (aritmetik sırası, ** sağ assosiyatif, == > & |, and > or). Geri kalanları parantez ile çöz. Tabloyu cep referansı olarak tut; ihtiyacın olan zaman bak.
Yorumlar & Soru-Cevap
(0)Yorum yazmak için giriş yap.
Yorumlar yükleniyor...
Related Content
Modül 1: Giriş ve Kurulum
Python Nedir, Neden Bu Kadar Popüler?
Start LearningModül 1: Giriş ve Kurulum
Python Sürümlerinin Tarihi: 2'den 3.14'e, AI Winter'lardan 'No-GIL' Devrimine
Start LearningModül 1: Giriş ve Kurulum