Ana içeriğe geç

Python Değişken Kapsamı ve LEGB Kuralı Açıklandı

Değişken kapsamlarının ne olduğunu öğrenin ve 'LEGB' kuralına aşina olun. Ayrıca global ve nonlocal anahtar sözcüklerini iş başında göreceğiniz senaryolarla karşılaşacaksınız.
· 8 dk. oku

Yapay Zeka ile Keşfedin

Yalnızca birkaç satır yazdıktan sonra “name is not defined” veya “local variable referenced before assignment” mesajlarını görmek sinir bozucudur. Kod doğru görünüyor ama Python aynı fikirde değildir. Bunun temel nedeni neredeyse her zaman kapsamdırr: bir ismin nerede görünür olduğu ve o anda hangi nesneye karşılık geldiği.

Python’un isim aramasını—genellikle LEGB kuralı olarak özetlenir—anladığınızda, bu hatalar öngörülebilir ve kolayca düzeltilebilir hale gelir. Bu eğitimde, Python’da değişkenleri ve kapsamları adım adım ele alacağım.

Değişken Nedir?

Değişken, bir nesneye bağlı (bağlı) bir isimdir. Python’da atama operatörü = ile bir bağ oluşturursunuz. İsimler türlü değildir; herhangi bir nesneyi (string, int, list, function vb.) gösterebilirler.

customer_name = "Ava Torres"
order_count = 1
total_cents = 1 + 2 * 300  # evaluated first, then bound

Sözdizimi hatalarından ve ince hatalardan kaçınmak için değişken adı verirken şu kurallara ve geleneklere uyun.

  • Yalnızca harfler, rakamlar ve alt çizgi kullanın; isimler bir rakamla başlayamaz.
  • True, for veya class gibi anahtar sözcükleri isim olarak kullanmayın.
  • list, dict, sum veya max gibi yerleşikleri gölgelemekten kaçının.
  • Okunabilirlik için snake_case tercih edin (PEP 8).

Aşağıdaki örnekler nelerin yapılmaması gerektiğini ve Python’un hangi hataları verdiğini gösterir:

first string value = "First string"  # spaces not allowed
# SyntaxError: invalid syntax

1st_value = 10  # cannot start with a digit
# SyntaxError: invalid decimal literal

True = "yes"  # cannot assign to a keyword
# SyntaxError: cannot assign to True

Python’da Kapsam Nasıl Çalışır (LEGB)

Kapsam, bir ismin görünür olduğu kod bölgesidir. Bir ismi kullandığınızda Python şu sırayla arar (LEGB):

  • Local: mevcut fonksiyonun kapsamı.
  • Enclosing: iç içe fonksiyonlar için dıştaki fonksiyon kapsamları.
  • Global: modülün en üst düzeyi (modül ad alanı).
  • Built-in: Python’un builtins içinde tanımladığı isimler (örneğin len, print).

İsimler ad alanlarında yaşar (isimleri nesnelere eşleyen sözlükler gibi düşünün). Kapsam, kodun belirli bir noktasında bir ismi çözmek için Python’un hangi ad alanlarına baktığıyla ilgilidir.

Yerel kapsam

Bir fonksiyon içinde atanan isimler, aksi belirtilmedikçe o fonksiyona yereldir. Fonksiyonun dışında görünür değillerdir.

def show_order_id():
    order_id = 42
    print("inside function:", order_id)

show_order_id()
print("outside function:", order_id)  # NameError

Python kapsamı derleme zamanında belirler. Bir fonksiyon gövdesinin herhangi bir yerinde bir isme atama yapılıyorsa, o isim fonksiyon içindeki tüm kullanımlarda yerel kabul edilir—ve atamadan önce okumaya çalıştığınızda yaygın bir UnboundLocalError oluşur:

discount_rate = 0.10  # module-level (global)

def price_with_discount(amount_cents):
    print("configured discount:", discount_rate)  # looks local because of the assignment below
    discount_rate = 0.20  # assignment makes 'discount_rate' local in this function
    return int(amount_cents * (1 - discount_rate))

# UnboundLocalError: cannot access local variable 'discount_rate' where it is not associated with a value

Fonksiyonda modül düzeyindeki ismi kullanmak için ya ona atama yapmaktan kaçının ya da onu global olarak işaretleyin (aşağıda ele alınmıştır).

Kapsayan kapsam (kapanımlar)

İç içe fonksiyonlar, kendilerini hemen saran fonksiyondaki isimleri görebilir. Böyle bir ismi yeniden bağlamak (sadece okumak değil) için nonlocal bildirin.

def make_step_counter():
    count = 0  # enclosing scope for 'increment'

    def increment():
        nonlocal count  # rebind the 'count' in the nearest enclosing function
        count += 1
        return count

    return increment

step = make_step_counter()
print(step())  # 1
print(step())  # 2

nonlocal olmadan, increment() içinde count’a atama yapmak yeni bir yerel isim oluşturur ve dıştaki count değişmeden kalır.

Global kapsam

Bir modülün en üst düzeyinde atanan isimler, modülün global ad alanında yaşar. Her fonksiyon bunları okuyabilir. Bir fonksiyon içinden modül düzeyindeki bir isme atama yapmak için onu global olarak bildirin.

greeting = "Hello"

def greet_city(city_name):
    print(greeting, city_name)  # reads global

def set_greeting(new_greeting):
    global greeting
    greeting = new_greeting     # rebinds global

greet_city("Nairobi")  # Hello Nairobi
set_greeting("Hi")
greet_city("Nairobi")  # Hi Nairobi

global’ı ölçülü kullanın. Kodun test edilebilir ve öngörülebilir kalması için değerleri parametre olarak geçirmeyi ve sonuçları döndürmeyi tercih edin.

Yerleşik kapsam (ve anahtar sözcükler hakkında bir not)

Yerleşik kapsam, len, print ve Exception gibi isimleri içerir. Bunları gölgelemekten kaçının; aksi halde o kapsamda yerleşik işlevi kaybedersiniz.

list = [1, 2, 3]     # shadows the built-in 'list' constructor
list("abc")          # TypeError: 'list' object is not callable
del list             # fix by deleting the shadowing name

Anahtar sözcükler (if, for, def gibi) Python’un sözdiziminin parçasıdır, yerleşik ad alanının değil, ve asla tanımlayıcı olarak kullanılamazlar.

Bloklar, Döngüler ve Anlamalar

Python’un blok ifadeleri ve anlamaları, diğer dillerden gelen geliştiricileri sıkça şaşırtan belirli kapsam davranışlarına sahiptir.

if/for/while/with için blok kapsamı yoktur

Bu blokların içindeki atamalar, kapsayan kapsamı (fonksiyon veya modül) etkiler. Döngü değişkenleri de döngü bittikten sonra tanımlı kalır.

if True:
    status = "ready"
print(status)  # "ready"

for i in range(3):
    pass
print(i)  # 2 (the last value from the loop)

Anlamalar yineleme değişkenlerini izole eder

Liste, sözlük ve küme anlamalarının döngü değişkenleri için kendi yerel kapsamları vardır. Yineleme değişkeni çevreleyen kapsama sızmaz.

numbers = [1, 2, 3]
[x for x in numbers]
print("x" in globals() or "x" in locals())  # False

Python 3.12 (PEP 709), hız için anlamaları satır içine alırken bu izolasyonu korudu; hâlâ net, sızmayan döngü değişkenleri ve daha hızlı yürütme elde edersiniz.

global Anahtar Sözcüğünü Kullanma

Bir ismi global olarak bir fonksiyon içinde, modül düzeyindeki bir değişkeni yeniden bağlamanız gerektiğinde bildirin. Hangi değişkeni değiştirdiğinizin açık olması için bildirimi fonksiyonun başına yakın bir yere koyun.

tax_rate = 0.08

def configure_tax(rate):
    global tax_rate
    tax_rate = float(rate)

def total_with_tax(cents):
    return int(cents * (1 + tax_rate))

configure_tax(0.10)
print(total_with_tax(1000))  # 1100

nonlocal Anahtar Sözcüğünü Kullanma

En yakın kapsayan fonksiyon kapsamındaki bir ismi yeniden bağlamak için nonlocal kullanın. Bu, durum tutan kapanımlarda yaygındır.

def make_accumulator(start=0):
    total = start
    def add(amount):
        nonlocal total
        total += amount
        return total
    return add

acc = make_accumulator()
print(acc(5))   # 5
print(acc(10))  # 15

nonlocal’ın, bir kapsayan fonksiyonda tanımlı olmayan bir isim için kullanılması bir SyntaxError’dır. İsim global ise bunun yerine global kullanın.

locals() ve globals() 2025’te

Bu işlevler inceleme ve hata ayıklama için kullanışlıdır, değişken güncellemek için değil. Python 3.13’ten (PEP 667) itibaren, fonksiyon içindeki her locals() çağrısı bağımsız bir anlık görüntü döndürür. Bu anlık görüntüyü düzenlemek gerçek yerelleri değiştirmez. Bu davranışı Python 3.13’te aşağıdaki parçacığı çalıştırarak doğruladım:

def probe():
    project = "alpha"
    snap1 = locals()
    snap1["project"] = "beta"  # edits the snapshot only
    observed = project         # still "alpha"
    snap2 = locals()           # new snapshot
    return snap1["project"], observed, snap2["project"]

print(probe())  # ('beta', 'alpha', 'alpha')

globals()’ı modül ad alanı için benzer şekilde kullanın. Uygulama kodu yazarken dinamik aramalar yerine açık parametreleri ve dönüş değerlerini tercih edin.

Yaygın Tuzaklar ve Nasıl Düzeltilir

Bu hatalar, pratikte gördüğüm kapsamla ilgili hataların çoğunu oluşturur.

  • UnboundLocalError—fonksiyon içinde atamadan kaynaklanır: Python, bir isme fonksiyonda herhangi bir yerde atama varsa o ismi yerel sayar. Okumayı atamadan sonraya alın, ismi değiştirin ya da uygun şekilde global/nonlocal ekleyin.
  • Blok kapsamı beklemek: if/for/while/with içinde atanan isimler, kapsayan kapsamda kalıcıdır. Kapsamı sınırlamak için daha dar yardımcı fonksiyonlar kullanın.
  • Yerleşikleri gölgeleme: list, dict, sum, id veya min gibi isimlerden kaçının. customer_list veya min_allowed gibi açıklayıcı isimler seçin.
  • Kapanımlarda nonlocal’ı unutmak: Dıştaki bir fonksiyon değişkenini güncellemeyi amaçlıyorsanız, onu nonlocal olarak bildirin. Aksi halde yeni bir yerel oluşturur ve dıştaki değer değişmez.
  • Anahtar sözcükleri yerleşiklerle karıştırmak: Anahtar sözcükler (sözdizimi) asla isim olarak kullanılamaz. Yerleşikler gölgelenebilir ama gölgelenmemelidir.

Kapsamı Basit Tutan En İyi Uygulamalar

Bu alışkanlıklar kodu okumayı, test etmeyi ve hata ayıklamayı kolaylaştırır.

  • Küçük, odaklı fonksiyonları tercih edin. Değişkenleri işe yarayan en dar kapsamda tanımlayın.
  • Verileri parametrelerle içeri ve dönüş değerleriyle dışarı taşıyın. Modül düzeyindeki durumu en aza indirin.
  • Kapanımları bilinçli kullanın. Bir iç içe fonksiyonun hangi dış isimleri yakaladığını belgelendirin ve gerçekten yeniden bağlamanız gerektiğinde nonlocal kullanın.
  • Çatışmayan, açıklayıcı isimler seçin. Önde gelen alt çizgi (ör. _cache) dahili kullanım sinyali verir.
  • locals()/globals()’ı yapılandırma mekanizması değil, salt okunur tanılama olarak ele alın.

Sonuç

Python, isimleri Yerel → Kapsayan → Global → Yerleşik kapsamlarında arayarak çözer. Bu sırayı—ve ne zaman global veya nonlocal kullanmanız gerektiğini—anlamak, NameError ve UnboundLocalError gibi yaygın hataları ortadan kaldırır. Değişkenleri mümkün olan en küçük kapsamda tutun, yerleşikleri gölgelemekten kaçının ve kapanımları bilinçli kullanın. Bu zihinsel modelle fonksiyonlarınız öngörülebilir davranır ve kapsam sürpriz kaynağı olmaktan çıkar.

Sejal Jaiswal

Yazar

Sejal Jaiswal

Çeşitli sektörlerde çalıştım ve birden çok rol üstlendim: yazılım geliştirici, makine öğrenimi araştırmacısı, veri bilimci, ürün yöneticisi. Ancak özünde, öğrenmeyi ve bilgiyi paylaşmayı seven bir programcıyım!

Konular

İlgili