Skip to content

Mantıksal Operatörler: and, or, not — Short-circuit'ün Pythonic Sanatı

and, or, not görünüşte ilkokul mantığı ama Python'un short-circuit semantiği ile zarif validator'lar, default chain'leri, lazy evaluation pattern'leri yazabiliyorsun. Bu derste: De Morgan kanunları kod ile, any() ve all() built-in'leri, conditional expression, ve gerçek dünya validator + permission check örnekleri.

Şükrü Yusuf KAYA
18 min read
Beginner
Mantıksal Operatörler: and, or, not — Short-circuit'ün Pythonic Sanatı
🧮 Mantıksal operatörler — küçük ama her satırda
Bir programda 'koşul' demek genelde and/or/not içeriyor. Bu operatörlerin Python'a özgü davranışlarını (short-circuit, son değer dönme) bilmek, kodu hem kısalaştırıyor hem de subtle bug'lardan koruyor.

3 Mantıksal Operatör#

# and — ikisi de True ise True True and True # True True and False # False False and True # False (False'tan sonra True'ya bakmaz — short-circuit) False and False # False # or — en az biri True ise True True or False # True (True'dan sonra False'a bakmaz — short-circuit) False or True # True False or False # False # not — tersini al not True # False not False # True not 0 # True (0 falsy) not "hello" # False ("hello" truthy)
Bunlar bool dönüyor diye düşünebilirsin — ama hayır, Python'da
and
ve
or
bool değil, son değerlendirilen değeri dönüyor
:
# and: ilk falsy değer veya son truthy değer print(5 and 10) # 10 (ikisi de truthy, son dönüyor) print(0 and 10) # 0 (ilk falsy) print(None and "hello") # None print([] and "hello") # [] # or: ilk truthy değer veya son falsy değer print(5 or 10) # 5 (ilk truthy) print(0 or 10) # 10 (0 falsy, 10 dönüyor) print(None or [] or "x") # 'x' (ilki ikisi falsy, x truthy) print(0 or "" or None) # None (hepsi falsy, son dönüyor) # not: her zaman bool dönüyor print(not 5) # False print(not "x") # False print(not 0) # True print(not None) # True
Bu davranış JavaScript'le aynı ama C/Java'dan farklı (orada hep bool dönüyor).

Short-circuit evaluation — performans + güvenlik#

Python
and
/
or
operatörünü lazy değerlendiriyor:
# and: ilk operand False ise ikinciye bakmıyor def expensive_check(): print("pahalı işlem yapıldı") return True cached_result = False result = cached_result and expensive_check() # expensive_check çağrılmadı! Çıktı: (yok) print(result) # False # or: ilk operand True ise ikinciye bakmıyor cached_result = True result = cached_result or expensive_check() # expensive_check çağrılmadı! print(result) # True
Bu özellik iki amaca hizmet eder:

1. Performans — pahalı kontrol atlama#

if user and user.is_authenticated() and user.has_permission(): do_action() # user None ise: is_authenticated() çağrılmaz (hatadan korur) # is_authenticated False ise: has_permission() çağrılmaz (DB query atlandı)

2. Güvenlik — None safety#

# Tehlikeli (kontrolsüz) length = obj.data.length # obj None ise AttributeError! # Güvenli — short-circuit length = obj and obj.data and obj.data.length # obj None → length = None (kısa devre) # obj.data None → length = None # Hepsi truthy → gerçek length # Bu pattern Java versiyonu: obj?.data?.length (Optional chaining) # Python 3.x'te resmi optional chain yok, ama and chain ile yapılır
🚨 Tuzak:
and
chain'i
0
'ı falsy görüyor — sayısal değerlerde sorun:
# Tuzak count = obj and obj.count # obj.count = 0 ise → 0 dönüyor (False/0 ayrımı yok) # Doğrusu — explicit check count = obj.count if obj is not None else None

Default value chain —
or
ile#

Klasik Pythonic pattern: ilk truthy değeri seç.
# Tek-tek display_name = nickname or username or email or "Anonim" # nickname truthy ise ona düş; değilse username; değilse email; değilse default # Java'da: # String displayName = nickname != null && !nickname.isEmpty() ? nickname : # username != null && !username.isEmpty() ? username : # email != null && !email.isEmpty() ? email : "Anonim"; # Python — bir satır.
🚨 Sayısal değerlerde tuzak (önceki ders 8'den hatırla):
# Kullanıcı limit set etmemişse 100, set ettiyse o değer # user.limit = 0 olsa, 0 falsy olduğu için 100 dönüyor — istemediğin limit = user.limit or 100 # Doğrusu limit = user.limit if user.limit is not None else 100 # Walrus + None check limit = user.limit if (l := user.limit) is not None else 100 # Daha okunabilir hali yukarıdaki ternary
Sayısal default için
or
tehlikeli; explicit
is None
daha güvenli.

get(key, default)
ile dict default#

config = {"timeout": 30, "retries": 0} # 🚫 — retries 0 olduğu için 5 dönüyor! retries = config.get("retries") or 5 # ✅ retries = config.get("retries", 5) # missing key için 5; var ise değer print(retries) # 0 (var, 0)
dict.get(key, default)
"key yoksa default",
or
ile fark var. Subtle bug'lardan kaçın.

De Morgan Kanunları — boolean dönüştürme#

Mantık dersinde gördüğün:
NOT (A AND B) = (NOT A) OR (NOT B) NOT (A OR B) = (NOT A) AND (NOT B)
Python'da:
# Eşdeğer ifadeler not (x > 0 and y > 0) # ↔ x <= 0 or y <= 0 not (x > 0 or y > 0) # ↔ x <= 0 and y <= 0
Pratik kullanım: koşulu pozitif yazma.
# 🚫 Negatif (anlaması zor) if not (user.is_active and user.has_permission and user.email_verified): return "Yetkisiz" # ✅ Pozitif (De Morgan ile) if not user.is_active or not user.has_permission or not user.email_verified: return "Yetkisiz" # Veya guard clause (Modül 2/4 Pythonic deyim) if not user.is_active: return "Hesap aktif değil" if not user.has_permission: return "Yetkin yok" if not user.email_verified: return "E-posta doğrulanmamış"
Guard clause'lar her hata için ayrı mesaj veriyor — debug açısından çok daha iyi.

any()
ve
all()
— koleksiyonlar için
or
ve
and
#

# any: en az bir tane truthy varsa True print(any([0, False, None, 5])) # True print(any([0, False, None])) # False print(any([])) # False (boş — vacuously false) # all: hepsi truthy ise True print(all([1, 2, 3, 4])) # True print(all([1, 2, 0, 4])) # False print(all([])) # True (boş — vacuously true)
🤔
all([])
neden True? "Hepsi" iddia ediyor; boş kümede karşı örnek yok, dolayısıyla vacuously true (matematik mantığı).
any([])
False — hiç truthy yok.

Generator ile lazy#

# any/all generator'larla short-circuit yapıyor nums = [1, 2, 3, 0, 5, 6, 7] # 0 ile karşılaşınca durur (hepsi truthy değil) print(all(n > 0 for n in nums)) # False (0'a geldi, geri kalan yok) # 5 büyük olan var mı? print(any(n > 4 for n in nums)) # True (5'e geldi, durdu) # Pratik: liste boş veya tüm elemanlar None mı items = [None, None, None] if all(item is None for item in items): print("Hepsi None")

List comprehension'la birlikte#

users = [{"age": 25}, {"age": 17}, {"age": 30}] # Hepsi yetişkin mi all_adult = all(u["age"] >= 18 for u in users) # False # En az bir yaşlı (>50) var mı any_senior = any(u["age"] >= 50 for u in users) # False # Geçerli e-mail kontrolü def has_valid_emails(users): return all(re.match(EMAIL_PATTERN, u["email"]) for u in users)
any
/
all
validator pattern'lerinin temeli.

Conditional expression (ternary) —
x if cond else y
#

C/Java'da
?:
. Python'da farklı syntax:
# Genel form result = value_if_true if condition else value_if_false # Örnekler status = "yetişkin" if age >= 18 else "çocuk" # Default değer (None check) limit = config["limit"] if "limit" in config else 100 # Min ile birleşmiş clamped = x if x <= max_val else max_val # Aynı anlamda: clamped = min(x, max_val) # Nested weather = "sıcak" if temp > 30 else "ılık" if temp > 15 else "soğuk" # Çok nested okunmaz — match veya dict'le yer değiştir weather_map = { True: "sıcak", }
🎯 Pythonic pattern:
condition
orta yerde — okuduğunda "buna düşersem bu, değilse şu" mantığı.

vs Java/JS
?:
#

// Java String status = age >= 18 ? "yetişkin" : "çocuk";
# Python status = "yetişkin" if age >= 18 else "çocuk"
Python'un syntax'ı "doğal İngilizce" gibi. JS/Java daha kompakt ama Python tasarımı okunabilirliği önceliyor.

and
/
or
ile ternary trick'i#

# Python 2.4 öncesi (ternary yoktu) result = condition and "true_val" or "false_val" # Çalışıyor ama tehlikeli — "true_val" falsy ise (örn 0, "") result = (5 > 3) and 0 or "default" # "default" (0 falsy yüzünden!) # Kesinlikle ternary kullan result = 0 if (5 > 3) else "default" # 0 (doğru)
Modern Python'da bu trick'ten kaçın; ternary expression doğal yol.

Pratik: Validator pattern'leri#

Form input kontrol etmek için
and
/
or
ile zarif validator yazılır:
def validate_password(password): """Tüm kuralları kontrol et.""" return ( len(password) >= 8 and any(c.isupper() for c in password) and any(c.islower() for c in password) and any(c.isdigit() for c in password) and any(c in "!@#$%^&*" for c in password) ) # Test print(validate_password("Abcd1234!")) # True print(validate_password("Short!")) # False (kısa) print(validate_password("nodigits!")) # False (rakam yok) # Daha açık feedback ile def validate_password_with_errors(password): errors = [] if len(password) < 8: errors.append("En az 8 karakter olmalı") if not any(c.isupper() for c in password): errors.append("Büyük harf içermeli") if not any(c.islower() for c in password): errors.append("Küçük harf içermeli") if not any(c.isdigit() for c in password): errors.append("Rakam içermeli") if not any(c in "!@#$%^&*" for c in password): errors.append("Özel karakter içermeli") return errors # Test errs = validate_password_with_errors("abc") if errs: print("Geçersiz:", errs) else: print("Geçerli!") # Çıktı: Geçersiz: ['En az 8 karakter olmalı', 'Büyük harf içermeli', ...]
İlk versiyon "true/false". İkinci versiyon "neden başarısız" — kullanıcı için daha yararlı.

Pratik: Permission check pattern'leri#

Web uygulamalarında klasik:
def can_edit_post(user, post): """Kullanıcı bu post'u düzenleyebilir mi?""" if user is None: return False if not user.is_authenticated: return False # Kendi post'u VEYA admin return user.id == post.author_id or user.is_admin def can_delete_post(user, post): """Daha katı: yazar VEYA admin VE post not locked.""" if not (user and user.is_authenticated): return False if post.is_locked: return False return user.id == post.author_id or user.is_admin # Aynı pattern Django, FastAPI, Flask permission system'ları
and
/
or
chain'leri "iş kuralları" oluştururken doğal Türkçe gibi okunuyor.

Compound conditions#

# Karmaşık business rule def can_apply_discount(user, cart): return ( user.is_authenticated and not user.is_blacklisted and cart.total >= 100 and ( user.is_premium or cart.has_first_time_buyer_discount or cart.has_promo_code ) )
Birden fazla kondisyon parantez ile gruplanmış. Bu okunabilir; her satır bir koşul.
🎯 İpucu: 4+ koşul varsa parantez ile satırlara böl. Tek satıra sıkıştırma.

Yaygın tuzaklar#

1.
and
/
or
öncelik sırası#

# Python: not > and > or True or False and False # = True or (False and False) # = True or False # = True # Beklenen değil mi? # Eğer (True or False) and False istiyordun: parantez gerek (True or False) and False # False
Operator precedence için sonraki ders detaylı işliyor. Parantez kullan, kafa karıştırma.

2.
and
ile
==
#

# Tuzak if x == 1 or 2 or 3: print("Eşit") # Aslında bu: # if (x == 1) or (2) or (3): # Yani: x == 1 ise True; değilse 2 (truthy) → her zaman True! # Doğrusu if x == 1 or x == 2 or x == 3: ... # Veya Pythonic if x in (1, 2, 3): ...
Yeni başlayanların yaptığı klasik hata. Her karşılaştırmayı ayrı yaz.

3.
is
vs
==
(tekrar uyarı)#

# 🚫 if x is True: ... # ✅ if x: ... # Veya açıkça if x == True: # nadiren ... # Sentinel'lar için is if x is None: ...

4. Bool vs int truthiness#

# Tuzak — int 0 falsy, int 1 truthy if some_int and other_int: ... # Eğer 0 anlamlı ise (count gibi), explicit check if some_int is not None and other_int is not None: ...

5. Döngüde short-circuit pattern'i unutma#

# any/all generator'la lazy items = [...] # 1M eleman # 🚫 Önce listeyi yarat, sonra kontrol et results = [item.is_valid for item in items] # 1M eleman compute all_valid = all(results) # ✅ Lazy — invalid bulunca dur all_valid = all(item.is_valid for item in items)
Generator + any/all = early exit + memory efficient.

6.
not in
vs
!= ... and ... !=
#

# 🚫 Uzun if x != 1 and x != 2 and x != 3: ... # ✅ if x not in (1, 2, 3): ... # Set ile (büyük listeler için O(1) lookup) if x not in {1, 2, 3}: ...
in
ve
not in
operatörleri
__contains__
magic method ile çalışıyor; tuple/list'te O(n), set/dict'te O(1).

Bu derste neler kazandın?#

3 mantıksal operatör — 'and', 'or', 'not' — Python'a özgü davranışlar.
Short-circuit evaluation — performans + None safety.
Default chain pattern — 'a or b or c or default' (sayısal'da dikkat).
De Morgan kanunları — 'not (A and B) = not A or not B'.
Guard clause — negatif iç içe yerine erken-return ile sade.
'any()' ve 'all()' — koleksiyonlar için 'or'/'and'. Generator'la short-circuit.
Vacuous truth — 'all([])' True, 'any([])' False.
Conditional expression 'x if cond else y' — Python ternary.
Validator pattern — şifre kontrolü, hata listesi.
Permission check pattern — web app authorization.
6 yaygın tuzak — precedence, '==' zinciri, 'is'/'==', bool/int truthiness, lazy any/all, in/not in.
Sıradaki ders: Bit-level operatörler (
&
,
|
,
^
,
~
,
<<
,
>>
). Network protocols, permission flags, color manipulation, bit manipulation tricks. AI'ın işine yaramayacağını sandığın ama bir gün lazım olacak konular.

Frequently Asked Questions

İkisi de. **Avantaj**: Default chain (`name or 'Anon'`), None safety (`obj and obj.attr`). **Dezavantaj**: Sayısal değerlerde sürpriz (`x or 100` → x=0 ise 100 dönüyor). Modern alternatif: walrus + ternary daha açık (`x if x is not None else 100`). Pratik kural: Container/string için `or` OK; sayısal için explicit.

Yorumlar & Soru-Cevap

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

Related Content

Mantıksal Operatörler: and, or, not — Short-circuit'ün Pythonic Sanatı | Python Programlama