Python'da Paket Açma Operatörleri (*, **) Nasıl Kullanılır?
Yayınlanan: 2021-07-02Python en çok kullanılan programlama dilidir. Bugün Python'da temel - ancak genellikle göz ardı edilen - özelliklerinden birini kullanmayı öğreneceksiniz.
Muhtemelen * ve ** diğerlerinin kodunda görmüşsünüzdür, hatta amaçlarının ne olduğunu bilmeden bunları kullanmışsınızdır. Paket açma kavramını ve daha fazla Pythonic kodu yazmak için nasıl kullanılacağını inceleyeceğiz.
Bu öğreticiyi okurken faydalı bulacağınız kavramların bir listesi:
- İterable: bir döngü için, kümeler gibi, listeler, küpe ve Sözlüklerle yinelenebilen herhangi bir sekans
- Callable : Çift parantez () kullanılarak çağrılabilen bir Python nesnesi, örneğin, myfunction()
- Kabuk: Python kodunu çalıştırmamıza izin veren etkileşimli çalışma zamanı ortamı. Bir terminalde “python” çalıştırarak onu çağırabiliriz.
- Değişken: Bir nesneyi saklayan ve ayrılmış bir hafıza konumuna sahip sembolik isim.
En sık karşılaşılan kafa karışıklığı ile başlayalım: Python'daki yıldız işaretleri aynı zamanda aritmetik operatörlerdir. Bir yıldız işareti (*) çarpma için kullanılırken, ikisi (**) üs alma anlamına gelir.
Bunu bir Python kabuğu açıp şunu yazarak kanıtlayabiliriz:
>>> 3*3 9 >>> 3**3 27Not: Bu öğreticiyi takip etmek için Python 3'ün kurulu olması gerekir. Eğer kurulu değilse Python kurulum kılavuzumuza bakın.
Gördüğünüz gibi, ilk sayıdan sonra ve ikinciden önce yıldız işareti kullanıyoruz. Bunu gördüğünüzde, aritmetik operatörleri kullanıyoruz demektir.
Öte yandan, paketini açmak için yinelenebilirden önce yıldız işaretlerini (*, **) kullanırız - örneğin:
>>> *range(1, 6), (1, 2, 3, 4, 5) >>> {**{'vanilla':3, 'chocolate':2}, 'strawberry':2} {'vanilla': 3, 'chocolate': 2, 'strawberry': 2}Anlamadıysanız endişelenmeyin, bu sadece Python'da paketin açılması için bir önsöz. Öyleyse devam edin ve tüm öğreticiyi okuyun!
Açmak nedir?
Paketi açma, listeler, tanımlama grupları ve sözlükler gibi yinelenebilir öğelerin dışarı çıkarılması işlemidir. Bunu bir kutuyu açıp kablolar, kulaklıklar veya USB gibi farklı öğeleri çıkarmak olarak düşünün.

Daha iyi anlamak için aynı örneği koda çevirelim:
>>> mybox = ['cables', 'headphones', 'USB'] >>> item1, item2, item3 = myboxGördüğünüz gibi, mybox listesinin içindeki üç öğeyi item1, item2, item2 adlı üç değişkene atadık . Bu tür bir değişken ataması, Python'da paket açmanın temel konseptidir.
Her bir öğenin değerini almaya çalışırsanız, item1 'in “kablolar” anlamına geldiğini, item2 ' nin “kulaklıklar” anlamına geldiğini vb. fark edeceksiniz.
>>> item1 'cables' >>> item2 'headphones' >>> item3 'USB'Buraya kadar, bu kodla her şey yolunda gibi görünüyor, ama ya içinde daha fazla öğe bulunan bir listeyi açmak istiyorsak - aynı miktarda atanmış değişkeni koruyarak?
>>> newbox = ['cables', 'headphones', 'USB', 'mouse'] >>> item1, item2, item3 = newbox Traceback (most recent call last): File "<stdin>", line 1, in <module> ValueError: too many values to unpack (expected 3)Muhtemelen bu tür bir hata bekliyordunuz. Temelde üç değişkene 4 liste öğesi atıyoruz, Python doğru değerleri atamayı nasıl başarıyor?
Değil, çünkü “açılacak çok fazla değer” mesajıyla bir ValueError alıyoruz. Bu, solda üç değişken ve sağda (yeni kutu listesine karşılık gelen) dört değer ayarladığımız için oluyor.
Benzer bir işlem yapmaya çalışırsanız, ancak paketten çıkarılacak değerlerden daha fazla değişken varsa, biraz farklı bir mesajla birlikte başka bir ValueError alırsınız:
>>> lastbox = ['cables', 'headphones'] >>> item1, item2, item3 = lastbox Traceback (most recent call last): File "<stdin>", line 1, in <module> ValueError: not enough values to unpack (expected 3, got 2)Not: Listelerle çalışıyoruz, ancak bu açma biçimini herhangi bir yinelenebilir (listeler, kümeler, demetler, sözlükler) ile kullanabilirsiniz.
Peki bu durumu nasıl aşacağız? Yinelenebilir bir öğenin tüm öğelerini herhangi bir hata almadan birkaç değişkene açmanın bir yolu var mı?
Elbette var ve buna paket açma operatörü veya yıldız işareti operatörü (*, **) denir. Python'da nasıl kullanılacağını görelim.
* operatörü ile Listeler Nasıl Açılır
Yıldız operatörü (*) henüz atanmamış bir yinelenebilirin tüm değerlerini açmak için kullanılır.
Bir listenin ilk ve son elemanını indeks kullanmadan almak istediğinizi varsayalım, bunu yıldız operatörü ile yapabiliriz:
>>> first, *unused, last = [1, 2, 3, 5, 7] >>> first 1 >>> last 7 >>> unused [2, 3, 5]Takdir edebileceğiniz gibi, kullanılmayan tüm değerleri yıldız operatörü ile alıyoruz. Değerleri atmanın tercih edilen yolu, bazen "kukla değişken" olarak kullanılan bir alt çizgi değişkeni (_) kullanmaktır.
>>> first, *_, last = [1, 2, 3, 5, 7] >>> _ [2, 3, 5]Listede yalnızca iki öğe olsa bile bu numarayı kullanabiliriz:
>>> first, *_, last = [1, 2] >>> first 1 >>> last 2 >>> _ []Bu durumda, alt çizgi değişkeni (kukla değişken) boş bir liste saklar, böylece etraflarındaki diğer iki değişken listenin mevcut değerlerine erişebilir.
Genel sorun giderme
Yinelenebilir bir öğenin benzersiz bir öğesini açabiliriz. Örneğin, şöyle bir şey bulursunuz:
>>> *string = 'PythonIsTheBest'Ancak yukarıdaki kod bir SyntaxError döndürür:
>>> *string = 'PythonIsTheBest' File "<stdin>", line 1 SyntaxError: starred assignment target must be in a list or tupleBunun nedeni, PEP spesifikasyonuna göre:
Basit bir atamanın sol tarafında bir demet (veya liste)
Yinelenebilir bir değişkenin tüm değerlerini tek bir değişkene açmak istiyorsak, bir demet oluşturmalıyız, bu nedenle basit bir virgül eklemek yeterli olacaktır:
>>> *string, = 'PythonIsTheBest' >>> string ['P', 'y', 't', 'h', 'o', 'n', 'I', 's', 'T', 'h', 'e', 'B', 'e', 's', 't']Başka bir örnek, bir sayı dizisi döndüren aralık işlevini kullanmak olabilir.

>>> *numbers, = range(5) >>> numbers [0, 1, 2, 3, 4]Artık yıldız işaretli listeleri ve demetleri nasıl açacağınızı bildiğinize göre, paket açma sözlüklerine girme zamanı.
** operatörü ile Sözlükler Nasıl Açılır
Listeleri ve demetleri açmak için tek bir yıldız işareti kullanılırken, sözlükleri açmak için çift yıldız işareti (**) kullanılır.
Ne yazık ki, tuple ve listelerle yaptığımız gibi bir sözlüğü tek bir değişkene açamayız. Bu, aşağıdakilerin bir hata vereceği anlamına gelir:
>>> **greetings, = {'hello': 'HELLO', 'bye':'BYE'} ... SyntaxError: invalid syntaxAncak callables ve diğer sözlüklerin içinde ** operatörünü kullanabiliriz. Örneğin, diğer sözlüklerden yapılmış birleştirilmiş bir sözlük oluşturmak istiyorsak aşağıdaki kodu kullanabiliriz:
>>> food = {'fish':3, 'meat':5, 'pasta':9} >>> colors = {'red': 'intensity', 'yellow':'happiness'} >>> merged_dict = {**food, **colors} >>> merged_dict {'fish': 3, 'meat': 5, 'pasta': 9, 'red': 'intensity', 'yellow': 'happiness'}Bu, bileşik sözlükler oluşturmanın oldukça kısa bir yoludur, ancak Python'da paket açmanın ana yaklaşımı bu değildir.
Paket açmayı callables ile nasıl kullanabileceğimizi görelim
Fonksiyonlarda Paketleme: argümanlar ve kwargs
Muhtemelen argümanlar ve kwargs'leri sınıflarda veya işlevlerde uygulanmadan önce görmüşsünüzdür. Bakalım neden onları callable'larla birlikte kullanmamız gerekiyor.
* operatörüyle paketleme (args)
İki sayının çarpımını hesaplayan bir fonksiyonumuz olduğunu varsayalım.
>>> def product(n1, n2): ... return n1 * n2 ... >>> numbers = [12, 1] >>> product(*numbers) 12Gördüğünüz gibi, liste numaralarını işlevin paketini açıyoruz, bu nedenle aslında aşağıdakileri çalıştırıyoruz:
>>> product(12, 1) 12Buraya kadar her şey yolunda gidiyor ama ya daha uzun bir listeden geçmek istersek? İşlev, yönetebileceğinden daha fazla argüman aldığı için kesinlikle bir hata oluşturacaktır.
>>> numbers = [12, 1, 3, 4] >>> product(*numbers) ... TypeError: product() takes 2 positional arguments but 4 were givenTüm bunları, listeyi doğrudan işlevin üzerinde paketleyerek çözebiliriz; bu, içinde yinelenebilir bir öğe oluşturur ve işleve herhangi bir sayıda argüman iletmemize izin verir.
>>> def product(*args): ... result = 1 ... for i in args: ... result *= i ... return result ... >>> product(*numbers) 144Burada, args parametresini yinelenebilir olarak ele alıyoruz, öğeleri arasında dolaşıyoruz ve tüm sayıların çarpımını döndürüyoruz. Sonucun başlangıç numarasının nasıl bir olması gerektiğine dikkat edin çünkü sıfır ile başlarsak fonksiyon her zaman sıfır döndürür.
Not: args yalnızca bir kuraldır, başka herhangi bir parametre adını kullanabilirsiniz.
Ayrıca, yerleşik yazdırma işlevinde olduğu gibi, bir liste kullanmadan işleve rastgele sayılar da iletebiliriz.
>>> product(5, 5, 5) 125 >>> print(5, 5, 5) 5 5 5Son olarak, bir fonksiyonun argümanlarının nesne tipini bulalım.
>>> def test_type(*args): ... print(type(args)) ... print(args) ... >>> test_type(1, 2, 4, 'a string') <class 'tuple'> (1, 2, 4, 'a string')Yukarıdaki kodda belirtildiği gibi, argümanların türü her zaman Tuple olacaktır ve bunun içeriği, işleve iletilen tüm anahtar sözcük olmayan argümanlar olacaktır.
** operatörü ile paketleme (kwargs)
Daha önce gördüğümüz gibi, ** operatörü yalnızca sözlükler için kullanılır. Bu, bu operatörle, işleve bir parametre olarak anahtar/değer çiftlerini geçirebileceğimiz anlamına gelir.
Şimdi, konumsal bir "ad" argümanı ve tanımsız miktarda anahtar kelimeli argüman alan bir make_person işlevi oluşturalım.
>>> def make_person(name, **kwargs): ... result = name + ': ' ... for key, value in kwargs.items(): ... result += f'{key} = {value}, ' ... return result ... >>> make_person('Melissa', id=12112, location='london', net_worth=12000) 'Melissa: id = 12112, location = london, net_worth = 12000, 'Gördüğünüz gibi, **kwargs ifadesi, anahtar sözcüklü tüm argümanları, işlev içinde yineleyebileceğimiz bir sözlüğe dönüştürür.
Not: kwargs, bu parametreyi istediğiniz gibi adlandırabileceğiniz bir kuraldır.
Biz args ile yaptığımız aynı şekilde kwargs türünü kontrol edebilirsiniz:
>>> def test_kwargs(**kwargs): ... print(type(kwargs)) ... print(kwargs) ... >>> test_kwargs(random=12, parameters=21) <class 'dict'> {'random': 12, 'parameters': 21}Kwargs dahili değişkeni her zaman, işleve geçirilen anahtar/değer çiftlerini depolayan bir sözlük olur.
Son olarak, aynı fonksiyonda args ve kwarg'ları kullanalım :
>>> def my_final_function(*args, **kwargs): ... print('Type args: ', type(args)) ... print('args: ', args) ... print('Type kwargs: ', type(kwargs)) ... print('kwargs: ', kwargs) ... >>> my_final_function('Python', 'The', 'Best', language='Python', users='A lot') Type args: <class 'tuple'> args: ('Python', 'The', 'Best') Type kwargs: <class 'dict'> kwargs: {'language': 'Python', 'users': 'A lot'}Çözüm
Paket açma operatörleri günlük görevlerde gerçekten kullanışlıdır, artık bunları hem bireysel ifadelerde hem de fonksiyon parametrelerinde nasıl kullanacağınızı biliyorsunuz.
Bu eğitimde şunları öğrendiniz:
- Tuples ve listeler için * ve sözlükler için ** kullanırsınız
- Paket açma operatörlerini işlevlerde ve sınıf kurucularında kullanabilirsiniz.
- args , anahtar olmayan parametreleri işlevlere geçirmek için kullanılır
- kwargs , anahtar sözcüklü parametreleri işlevlere geçirmek için kullanılır.
