Soru geçmişi:
Unpacking için * ve ** operatörleri Python'da uzun zamandır var ama her sürümle birlikte kullanımları genişledi (örneğin, Python 3.5 ile birlikte birkaç koleksiyonu * ve ** ile birleştirme desteği eklendi). Bu operatörler, koleksiyonlarla çalışmayı daha esnek hale getirir, özellikle de argümanları geçirme ve fonksiyonlarda toplama sırasında.
Sorun:
Dizilerle, değişken sayıda argüman içeren parametrelerin geçişinde unpacking olmadan çalışırken, koleksiyonların boyutunu kontrol etmek ve döngüler yazmak zorunluluğu ortaya çıkıyor. Yanlış kullanım bu operatörlerin karıştırılmasında kolay hatalara neden olabilir.
Çözüm:
* operatörü dizilerin (list, tuple, set) unpacking'i için, ** operatörü ise fonksiyonları çağırırken veya birkaç sözlüğü birleştirirken sözlüklerin unpacking'i için tasarlanmıştır. Argümanları zarif bir şekilde iletmeyi, koleksiyonları birleştirmeyi ve rastgele yapıları fonksiyon parametrelerine kolayca dönüştürmeyi sağlar.
Kod örneği:
def foo(a, b, c): print(a, b, c) args = (1, 2, 3) foo(*args) # 1 2 3 params = {'a': 10, 'b': 20, 'c': 30} foo(**params) # 10 20 30 list1 = [1, 2] list2 = [3, 4] combined = [*list1, *list2] print(combined) # [1, 2, 3, 4]
Anahtar özellikler:
*sequence, elemanları ayrı pozisyonel argümanlar olarak geçirirken, **dict isimli argümanlar olarak geçirir.[*a, *b] ve {**d1, **d2} ile koleksiyonları şık bir şekilde birleştirme ve kopyalama yapabilirsiniz.*** ve 'yi karmaşık koleksiyonlar için kullanabilir miyiz?
Fonksiyon çağrısında * yalnızca pozisyonel argümanlarla, ** ise yalnızca isimli argümanlarla çalışır. Ayrıştırılmamış bir dict * veya bir dizi ** olarak geçtiğinde hata ortaya çıkar.
def foo(a, b): print(a, b) foo(*{'a': 1, 'b': 2}) # Çıktı: a b (sözlüğün anahtarları, değerleri değil!)
**{**d1, d2} ile dict birleştirirken anahtar isimleri kesişirse ne olur?
Sonuçta bu anahtara sahip son sözlüğün değeri olacak.
d1 = {'x': 1, 'y': 2} d2 = {'y': 33, 'z': 44} merged = {**d1, **d2} print(merged) # {'x': 1, 'y': 33, 'z': 44}
List comprehension veya dict comprehension içinde * ve ** kullanabilir miyiz?
Evet, Python 3.5 itibarıyla bu geçerlidir. Örneğin:
lst = [1, 2, *range(3, 6)] # [1, 2, 3, 4, 5] dct = {**{'a': 1}, 'b': 2, **{'c': 3}}
* ile dict geçişi (yalnızca anahtarlar unpack edilir).Bir geliştirici, işlevine bir dict alır ve onu * ile ayrıştırır yerine ** kullanmaz. Beklenmeyen bir davranış ortaya çıkar: işlevine değerler değil, anahtarlar gelir.
Artılar:
Hata kodu hemen çökmez, “çalışıyor” gibi görünür.
Eksiler:
Gizli hatalar ve beklenen mantığa uyumsuzluk.
Parametrelerin doğru bir şekilde **kwargs ile geçirilmesi, sözlüklerin düzgün birleştirilmesi, * kullanarak dinamik dizi birleştirilmesi.
Artılar:
Maksimum esneklik, kodun sadeliği, yeniden yapılandırma kolaylığı.
Eksiler:
Büyük sayıda parametre ve koleksiyonlar ile çalışırken, isimlere ve sıraya dikkat etmek önemlidir, aksi halde hatalar ortaya çıkabilir.