ProgramlamaBackend Geliştirici

Python'da argümanların referansla ve değerle iletilmesi nedir? Python bu mekanizmayı nasıl gerçekleştirir ve fonksiyon tasarımı sırasında bunları ayırt etmenin önemi nedir?

Hintsage yapay zeka asistanı ile mülakatları geçin

Cevap.

Python'un fonksiyonlarda argümanları nasıl ilettiğini anlamak, veri değişikliklerini önlemek ve kod tasarımını doğru bir şekilde yapmak için son derece önemlidir.

Konunun Geçmişi

C veya Java gibi geleneksel programlama dillerinde, değerle iletim (copy by value) veya referansla iletim (copy by reference) kullanılır. Ancak Python'da farklı bir model vardır — call by object reference (bazen "call by sharing" olarak adlandırılır).

Sorun

Pek çok geliştirici, Python'un her zaman ya referansla ya da değerle argümanları ilettiğini düşünmektedir. Bu, değiştirilebilir nesnelerin, çağrılan kodda beklenmedik bir şekilde değiştirilmesine neden olan durumlara yol açar.

Çözüm

Python'da fonksiyonun parametrelerinin değerleri, fonksiyona iletilen nesnelere referanslardır. Bu şunu ifade eder:

  • Eğer nesne değiştirilebilir (mutable: list, dict, set…) ise — fonksiyon içinde değiştirilebilir ve bu dışarıda yansır.
  • Eğer nesne değiştirilemez (immutable: int, str, tuple, frozenset) ise, fonksiyon içinde onu değiştirmeye çalışmak yeni bir nesne yaratacak ve dıştaki nesneyi etkilemeyecektir.

Örnek:

# list - değiştirilebilir (mutable) def add_item(lst): lst.append(42) my_list = [1, 2, 3] add_item(my_list) print(my_list) # [1, 2, 3, 42] # int - değiştirilemez (immutable) def add_num(x): x = x + 1 num = 10 add_num(num) print(num) # 10

Anahtar Özellikler:

  • Değiştirilebilir nesneler fonksiyon içinde değiştirilebilir — bu değişiklikler dışarıda görünür.
  • Değiştirilemez nesneler fonksiyon tarafından etkilenmez — sadece yeni nesneler oluşturulur.
  • Python otomatik olarak argümanları asla kopyalamaz, hatta değiştirilebilir yapılar her zaman "referansla" iletilir.

Yanıltıcı Sorular.

Python'da argümanlar her zaman referansla mı iletilir?

Hayır, Python'da nesnelere referanslar iletilir ve nesnenin nasıl davrandığı, değiştirilebilir olup olmadığına bağlıdır. Değiştirilemez bir nesne herhangi bir değişiklikte yeni bir nesne oluşturacaktır.

Fonksiyonda değiştirilebilir bir argümanı yeniden atayabilir miyim ve bu dış nesneyi etkileyebilir mi?

Hayır. Eğer fonksiyon içinde bir parametreye yeni bir değer atarsanız, dış nesne değişmeyecek - sadece yerel bir referansı değiştirirsiniz.

Örnek:

def reassign_list(lst): lst = [99, 100] my_list = [1, 2, 3] reassign_list(my_list) print(my_list) # [1, 2, 3]

Varsayılan olarak bir list alan bir fonksiyon, ikinci kez çağrıldığında neden garip çalışabilir?

Çünkü varsayılan değer bir kez oluşturulur — fonksiyon tanımlandığında ve eğer bu değiştirilirse (örneğin, bir öğe eklemek), tüm sonraki çağrılar için değişecektir.

def add_element(x, cache=[]): cache.append(x) return cache print(add_element(1)) # [1] print(add_element(2)) # [1, 2]

Tipik Hatalar ve Anti-Desenler

  • Varsayılan olarak değiştirilebilir argümanların kullanılması (son örnekte olduğu gibi).
  • Fonksiyonun geçen bir list veya dict'i değiştirmemesi beklentisi, oysa o kendi nesnesini değiştirir.
  • Değiştirilebilir ve değiştirilemez nesnelerle çalışırken fonksiyonların etkilerini karıştırmak.

Hayattan Bir Örnek

Olumsuz Durum

Bir programcı bir listeyi bir fonksiyona geçiriyor ve orijinal listesinin değişmeyeceğini bekliyor ama fonksiyon bir öğe ekliyor.

Artıları:

  • Hızlı çalışma, veri kopyalamaz.

Eksileri:

  • Beklenmedik yan etkiler, büyük kodda hatalar, eğer biri argümanın değişikliklerini bilmiyorsa.

Olumlu Durum

Bir programcı, geri dönecek bir şey lazım olduğunda, fonksiyon içinde listeyi açıkça kopyalar ama orijinalini değiştirmemek için:

def process_data(data): data = data.copy() # veya list(data) # kopya ile güvenli çalışma data.append('rapor') return data

Artıları:

  • İstenmeyen yan etkiler yok, orijinal korunur.

Eksileri:

  • Büyük nesnelerde — kopyalama için bellek/zaman maliyeti.