Python *args ve **kwargs’ın Açıklaması: Anlaşılır Örneklerle Esnek İşlevler
İşlev imzalarındaki bu yıldızlar göründüklerinden daha az gizemlidir. *args ve **kwargs’ın argümanları nasıl topladığını, aynı yıldızların bunları nasıl açtığını ve kötüye kullanılması zor fonksiyon imzalarının nasıl tasarlanacağını öğrenin.
*argsfazladan konumsal argümanları bir demet‘te toplar.**kwargsfazladan anahtar kelime argümanlarını bir sözlükte toplar.- Önemli olan
*ve**olduğundan isimler yalnızca bir kuraldır. - Aynı yıldız, bir işlevi çağırdığınızda bir listenin veya sözlüğün paketini açar.
Er ya da geç def handler(*args, **kwargs) gibi bir fonksiyonu okuyacak ve neyi kabul ettiğini merak edeceksiniz. Python *args ve **kwargs, bir fonksiyonun esnek sayıda argüman almasına izin verir. Dekoratörlere, sarmalayıcılara ve birçok kütüphane API’sine güç sağlarlar.
Bu kılavuz, Python’un bir işlevin nasıl çağrıldığını kontrol etmenize olanak tanıyan daha yeni yöntemlerin yanı sıra bunların her iki yönde de nasıl çalıştığını kapsar. Her örneği Python 3.13’te çalıştırdık ve gösterilen çıktı bu çalıştırmadan geliyor.
*args ne işe yarar?
Bir yıldızla yazılan bir parametre, tüm ekstra konumsal argümanları bir demet içinde toplar:
def total(*args):
print(type(args).__name__, args)
return sum(args)
print(total(1, 2, 3))
# tuple (1, 2, 3)
# 6
print(total())
# tuple ()
# 0
Hiçbir argüman olmadan, boş bir demet elde edersiniz, böylece işlev hala çalışır. İsim args bir kuraldır. *numbers aynı şekilde davranır ve daha açıklayıcı bir ad genellikle daha iyidir.
**kwargs ne yapar?
İki yıldız, ekstra anahtar kelime argümanlarını bir sözlüğe toplar:
def describe(**kwargs):
print(type(kwargs).__name__, kwargs)
describe(name="Asha", city="Pune")
# dict {'name': 'Asha', 'city': 'Pune'}
Normal bir sözlük olduğundan, onun üzerinden geçebilir, get() ile anahtarları arayabilir ve onu iletebilirsiniz. Anahtarlar aktarılma sırasını korur.
Parametre sırası
Parametre türlerini karıştırdığınızda Python belirli bir sıraya ihtiyaç duyar:
- Düzenli konumsal parametreler
*argümanlar- Yalnızca anahtar kelime parametreleri
**kwarg'lar
def order(item, qty=1, *extras, priority=False, **notes):
print(item, qty, extras, priority, notes)
order("pen")
# pen 1 () False {}
order("pen", 2, "gift wrap", "card", priority=True, note="leave at door")
# pen 2 ('gift wrap', 'card') True {'note': 'leave at door'}
Dikkat priority. *extras‘den sonra geldiği için yalnızca isimle ayarlanabilir, dolayısıyla başıboş konumsal bir argüman onu asla kazara belirleyemez. **kwargs‘ü daha önce koymaya izin verilmiyor ve testimiz bir SyntaxError ortaya çıkardı: “argümanlar var-anahtar kelime argümanını takip edemez”.
Arama yaparken paketi açma
Aynı yıldızlar çağrı yerinde tersten çalışır. Bir yıldız, bir listeyi veya tuple’ı konumsal argümanlara yayar ve iki yıldız, bir sözlüğü anahtar kelime argümanlarına yayar:
nums = [4, 5, 6]
total(*nums) # same as total(4, 5, 6) -> 15
settings = {"name": "Ben", "city": "Delhi"}
describe(**settings) # same as describe(name="Ben", city="Delhi")
Paketi açma yalnızca *args ve **kwargs kullanan işlevlerle değil, tüm işlevlerle çalışır. Yapılandırma bir sözlük olarak geldiğinde bu kullanışlıdır:
def connect(host, port, timeout=5):
return f"{host}:{port} (timeout {timeout})"
connect(**{"host": "db.local", "port": 5432})
# 'db.local:5432 (timeout 5)'
connect(**{"host": "db.local", "port": 5432, "ssl": True})
# TypeError: connect() got an unexpected keyword argument 'ssl'
Bu hata faydalıdır. **kwargs içermeyen bir işlev, bilinmeyen seçenekleri reddeder, böylece ayar adındaki bir yazım hatası sessizce göz ardı edilmek yerine yüksek sesle başarısız olur.
Yalnızca anahtar kelime bağımsız değişkenleri
İmzadaki isimsiz çıplak *, “bundan sonraki her şeyin anahtar kelimeyle iletilmesi gerektiği” anlamına gelir:
def make_user(name, *, admin=False):
return name, admin
make_user("Asha", admin=True)
# ('Asha', True)
make_user("Asha", True)
# TypeError: make_user() takes 1 positional argument but 2 were given
Bu, boole bayraklarını korumanın harika bir yoludur. make_user("Asha", True) gibi bir çağrı, okuyucuları True‘nin ne anlama geldiğini tahmin etmeye zorlar. admin=True‘ün gerekli kılınması her aramanın açıklayıcı olmasını sağlar.
Yalnızca konumsal bağımsız değişkenler
Python 3.8’den bu yana, bir / yalnızca konuma göre iletilebilen parametreleri işaretler:
def area(width, height, /):
return width * height
area(3, 4) # 12
area(width=3, height=4)
# TypeError: area() got some positional-only arguments
# passed as keyword arguments: 'width, height'
Bu, hiç kimsenin isimlere güvenemeyeceği için kütüphanenin bu parametreleri daha sonra kimsenin kodunu bozmadan yeniden adlandırmasına olanak tanır. Birkaç yerleşik bu şekilde çalışır. Örneğin, len(obj=[1]) çalışmıyor.
İpucu: Tam model def f(pos_only, /, normal, *, kw_only)‘dir. Üçüne de nadiren ihtiyaç duyarsınız, ancak / ve *‘ün ne anlama geldiğini bilmek, belgeleri ve kitaplık imzalarını okumanıza yardımcı olur.
Dekoratörler ve sarmalayıcılar
Her ikisini de birlikte kullanmanın gerçek dünyadaki ana nedeni budur. Bir sarmalayıcının genellikle orijinal işlevin aldığı argümanları kabul etmesi ve bunları değiştirmeden iletmesi gerekir:
import functools, time
def timed(func):
@functools.wraps(func)
def wrapper(*args, **kwargs):
start = time.perf_counter()
result = func(*args, **kwargs)
print(f"{func.__name__} took {time.perf_counter() - start:.4f}s")
return result
return wrapper
@timed
def slow_add(a, b, delay=0.01):
time.sleep(delay)
return a + b
print(slow_add(2, 3, delay=0.02))
# slow_add took 0.0205s
# 5
Sarmalayıcının slow_add‘in parametrelerini hiçbir şekilde bilmesine gerek yoktur, bu nedenle herhangi bir işlev için çalışır. Zamanlama rakamınız biraz farklı olacaktır. Python dekoratörlerine yönelik rehberimiz functools.wraps‘ü ve diğer ayrıntıları açıklamaktadır.
Birleştirme seçenekleri
** aynı zamanda bir sözlük değişmezi içinde de çalışır; bu, varsayılanların üzerine geçersiz kılmaları uygulamanın düzgün bir yolunu sunar:
defaults = {"theme": "light", "lang": "en"}
def build(**overrides):
return {**defaults, **overrides}
build(theme="dark")
# {'theme': 'dark', 'lang': 'en'}
Daha sonra anahtarlar kazanır, dolayısıyla geçersiz kılma varsayılanın yerini alır. Alt sınıflar da bu modeli, super().__init__(*args, **kwargs)‘de olduğu gibi, fazladan argümanları bir üst sınıfa iletmek için kullanır. super() hakkında daha fazla bilgi için Python sınıfları ve nesneleri‘ne bakın.
Hile sayfası
| Sözdizimi | Nerede | Anlamı |
|---|---|---|
def f(*args) |
Tanım | Ekstra konumsal argümanları bir demet içinde toplayın |
def f(**kwargs) |
Tanım | Ekstra anahtar kelime argümanlarını bir diktede toplayın |
def f(a, *, b) |
Tanım | b yalnızca anahtar kelimedir |
def f(a, /, b) |
Tanım | a yalnızca konumsaldır |
f(*items) |
Ara | Bir diziyi konumsal bağımsız değişkenlere yayma |
f(**options) |
Ara | Anahtar kelime bağımsız değişkenlerine bir dikte yayın |
{**a, **b} |
Değişmez | Sözlükleri birleştir |
[*a, *b] |
Değişmez | Yinelenebilirleri bir listede birleştirin |
Onlardan ne zaman kaçınmalı
Esnekliğin bir bedeli vardır. def create(**kwargs) olarak tanımlanan bir işlev, okuyuculara hangi seçeneklerin mevcut olduğu hakkında hiçbir şey söylemez ve editörler bunları otomatik olarak tamamlayamaz. Yazım hataları, herhangi bir şey başarısız olmadan önce birkaç katmandan sessizce geçebilir.
Bu nedenle, bir fonksiyonun neye ihtiyacı olduğunu bildiğinizde açık parametreleri tercih edin. Gerçekten esnekliğe ihtiyacınız olduğunda *args ve **kwargs‘yi kullanın: sarmalayıcılar, dekoratörler, argümanları başka bir işleve iletmek veya total(*numbers) gibi gerçek değişken uzunluklu bir giriş. Bir fonksiyonun çok sayıda adlandırılmış seçeneğe ihtiyacı varsa, dataclass de daha açıklayıcı olabilir.
Yaygın hatalar
Değişken bir varsayılan kullanma
Bu yıldızlarla ilgili değil, ancak genellikle onların yakınında görünüyor. İşlev tanımlandığında bir kez varsayılan değer oluşturulur ve ardından çağrılar arasında paylaşılır:
def bad(items=[]):
items.append(1)
return items
print(bad(), bad())
# [1, 1] [1, 1]
Her iki arama da aynı listeyi döndürdü ve bu listede artık iki öğe yer alıyordu. items=None‘i kullanın ve fonksiyonun içinde yeni bir liste oluşturun.
Diğer hatalar
- Paketi açmayı unutmak.
total(nums)‘yi aramak üç numara yerine bir listeyi iletir.total(*nums)yazın. - Yazım hatalarını yutmak.
**kwargs‘yi kabul eden ancak bilinmeyen anahtarları yok sayan bir işlev, yanlış yazılan seçenekleri gizler. Bunları doğrulayın veya**kwargs‘ten kaçının. - Aynı bağımsız değişkenin iki kez iletilmesi.
f(1, **{"a": 2}), buradaailk parametredir, “çoklu değer” hatasına neden olur. - Bir sarmalayıcıda iletmemek.
func(args, kwargs)çağrıldığında bir demet ve bir dikte iletilir. Doğru formfunc(*args, **kwargs)‘tür.
*args ve **kwargs için ipuçları yazın
*args ve **kwargs üzerindeki tür ipuçları koleksiyonun tamamını değil, her bir değeri açıklar. Bu birçok insanı şaşırtıyor:
def total(*prices: float) -> float:
return sum(prices) # prices is tuple[float, ...]
def tag(**attrs: str) -> str:
return " ".join(f'{k}="{v}"' for k, v in attrs.items()) # dict[str, str]
total(1.5, 2.5) # 4.0
tag(id="x", role="button") # id="x" role="button"
Burada prices kayan noktalı bir demet olarak ve attrs ise dizelerin sözlüğü olarak ele alınır. Anahtar kelime argümanlarının farklı türleri olduğunda, Python 3.12 kesin bir seçenek ekledi: TypedDict ile Unpack birleştirildi.
from typing import TypedDict, Unpack
class Options(TypedDict, total=False):
timeout: float
retries: int
def fetch(url: str, **opts: Unpack[Options]) -> None: ...
mypy veya Pyright gibi bir tür denetleyicisi daha sonra fetch(url, retries="3")‘i veya yanlış yazılmış bir seçenek adını reddedebilir, ki düz bir **kwargs asla bunu yapamaz. Ancak çalışma zamanı davranışı değişmez. Python 3.13 altında fetch("u", retries="3")‘ü çalıştırdığımızda şikayet etmeden yürütüldü, çünkü Python’un kendisi tür ipuçlarını zorunlu kılmıyor.
Kendinizi **kwargs için kabul edilen anahtarların uzun bir listesini belgelerken bulursanız, bunları yalnızca açık anahtar kelime parametreleriyle değiştirmeyi düşünün. Editörler daha sonra bunları otomatik olarak tamamlayabilir ve hatalar anında yakalanır.
Son sözler
İki yönü unutmayın. Tanım olarak yıldızlar toplanır. Bir aramada paketi açarlar. Çağrıları daha net hale getirmek için yalnızca anahtar kelimeden oluşan bağımsız değişkenler ekleyin ve bağımsız değişkenleri gerçekten ileten kod için **kwargs‘i ayırın. Alıştırma yapmak için, her çağrının argümanlarını kaydeden küçük bir dekoratör yazın ve onu birkaç farklı fonksiyonda kullanın.
Sık sorulan sorular
*args ve **kwargs arasındaki fark nedir?
*args, fazladan konumsal argümanları bir demet içinde toplar. **kwargs, fazladan anahtar kelime argümanlarını bir sözlüğe toplar. Bir fonksiyon her ikisini de birlikte kullanabilir.
Onlara args ve kwarg mı demem gerekiyor?
Hayır. İşi yıldızlar yapar, dolayısıyla *değerler veya **seçenekler eşit derecede geçerlidir. args ve kwargs basitçe geniş çapta tanınan bir gelenektir.
*args ve **kwargs hangi sırayla girmeli?
Önce normal parametreler, sonra *args, ardından yalnızca anahtar kelimeden oluşan parametreler ve son olarak **kwargs. Başka herhangi bir sipariş SyntaxError’a neden olur.
Bir işlev tanımında tek bir * ne anlama gelir?
Çıplak *, kendisinden sonraki her parametrenin anahtar kelime tarafından iletilmesi gerektiği anlamına gelir. Özellikle boole bayrakları için çağrıları daha net hale getirir.
Python işlevinde ne anlama gelir / ne anlama gelir?
/’den önceki parametreler yalnızca konumsaldır, bu nedenle arayanlar bunları adlarına göre iletemez. Bu özellik Python 3.8’e eklenmiştir.
Öğrenmeye devam et
Test, WordPress veya SEO konusunda yardıma mı ihtiyacınız var?
Ekiplerin daha iyi yazılımlar sunmasına ve sitelerini büyütmesine yardımcı oluyoruz. Bize ne üzerinde çalıştığınızı söyleyin, biz de bir sonraki adım için net bir öneride bulunalım.
Daha fazla kılavuz test, yapay zeka ve modern geliştirme
Bu makaleyi beğendiniz mi? Bir konu seçin ve doğrudan en yeni eğitimlerimize geçin.
Yapay Zeka Halüsinasyonları Açıklandı: Dil Modelleri Neden İşleri Düzeltiyor ve Nasıl Azaltılabilir?
Yapay zeka halüsinasyonları açıkladı: ne olduklarını, dil modellerinin bunları neden ürettiğini, yaygın türlerini, temellendirme ve yönlendirmelerle…
Makaleyi okuyun →DevOpsAçıklanan Ortam Değişkenleri: .env Dosyaları, Sırlar ve Yapılandırma Doğru Yapıldı
Çalıştırdığımız Python örnekleriyle açıklanan ortam değişkenleri: bunları okumak ve ayarlamak, neden her değerin bir dize olduğu, .env dosyaları, sü…
Makaleyi okuyun →Yazılım geliştirmeAPI Hız Sınırlamasının Açıklaması: Algoritmalar, Başlıklar ve 429 Hatalarının Ele Alınması
API hızı sınırlaması, çalıştırdığımız bir simülasyonla açıklanmıştır: belirteç kümesi, sabit pencere, kayan pencere, 429 yanıt, hız sınırı başlıklar…
Makaleyi okuyun →Test otomasyonuPython'da alay etme: Unittest.mock, patch ve Testleri Yalan Yapan Hatalar
Unittest.mock ile Python'da alay etme, test edildi: Sahte ve dönüş_değeri, yan_etki, bir adın kullanıldığı yerde yama uygulama, spesifikasyon ve oto…
Makaleyi okuyun →Yazılım testiKod Kapsamının Açıklaması: Hat ve Şube Kapsamı ve %100'ün Gerçek Anlamı
Kod kapsamı gerçek bir kapsama.py çalışmasıyla açıklanmıştır: hat, şube ve durum kapsamı, bir raporun okunması, %100 kapsamın neden hâlâ hataları ka…
Makaleyi okuyun →Veritabanları ve SQLSQL'de DELETE vs TRUNCATE vs DROP: Farklılıklar, Geri Alma ve Her Biri Ne Zaman Kullanılmalı
DELETE vs TRUNCATE vs DROP test edilmiş SQL ile açıklandı: her birinin neyi kaldırdığı, geri aldığı, tetiklediği, kimlik sıfırlaması, hızı ve Postgr…
Makaleyi okuyun →Veritabanları ve SQLAçıklanan SQL Görünümleri: Örneklerle Tuzakları Oluşturun, Kullanın ve Önleyin
Çalıştırdığımız sorgularla açıklanan SQL görünümleri: görünüm oluşturma, canlı sonuçlar, sütunları gizleme, performans, güncellenebilir ve gerçekleş…
Makaleyi okuyun →Yazılım geliştirmeTypeScript Arayüzü ve Tür: Gerçek Farklılıklar, Derleyiciyle Test Edildi
TypeScript arayüzü ve türü, gerçek derleyiciyle kontrol edildi: her ikisinin de yapabileceği, yalnızca birinin yapabileceği, bildirim birleştirme, g…
Makaleyi okuyun →Yazılım geliştirmePython *args ve **kwargs'ın Açıklaması: Açık Örneklerle Esnek Fonksiyonlar
Python *args ve **kwargs çalıştırdığımız kodla açıklanmıştır: paketleme ve paketten çıkarma, parametre sırası, yalnızca anahtar kelime ve yalnızca k…
Makaleyi okuyun →Yazılım geliştirmePython Lambda İşlevleri: Söz Dizimi, Gerçek Kullanımlar ve Ne Zaman Kullanılmaması Gerektiği
Çalıştırdığımız kodla açıklanan Python lambda işlevleri: sözdizimi, anahtarla sıralama, harita ve filtre, kapatmalar, geç bağlama tuzağı ve normal b…
Makaleyi okuyun →Yapay zekâYapay Zeka Ajanları Nelerdir? Çalıştırabileceğiniz Basit Bir Aracı Döngüsüyle Nasıl Çalışırlar?
Yapay zeka ajanları nedir? Aracı döngüsüne, araçlara, belleğe ve korkuluklara ilişkin basit bir kılavuz, çalıştırdığımız küçük bir Python döngüsü, g…
Makaleyi okuyun →DevOpsİzleme ve Gözlemlenebilirlik: Günlükler, Metrikler ve İzlerle Gerçek Fark
İzleme ve gözlemlenebilirliğin açıklanması: bilinen ve bilinmeyen arızalar, günlükler, ölçümler ve izler, ödeme olayının gözden geçirilmesi, altın s…
Makaleyi okuyun →DevOpsDocker Birimleri ve Bağlama Bağlantıları: Konteyner Verilerini Doğru Şekilde Kalıcılaştırın
Docker birimleri ile bağlama bağlamaları arasındaki karşılaştırma açıklandı: kapsayıcı verilerinin neden kaybolduğu, adlandırılmış birimler, bağlama…
Makaleyi okuyun →Test otomasyonuTDD ve BDD: Temel Farklılıklar, Her İki Şekilde Geliştirilmiş Bir Özellik ve Her Birinin Ne Zaman Kullanılacağı
TDD ve BDD, her iki yönde de oluşturulmuş bir indirim özelliğiyle açıklandı: çalıştırdığımız kodla kırmızı-yeşil-refactor, Verilen-Ne Zaman-O Zaman …
Makaleyi okuyun →Yazılım geliştirmeGit merge vs rebase: farklar, örnekler ve hangisi ne zaman kullanılır
Git merge vs rebase; gerçek log çıktısı, karşılaştırma tablosu, rebase'in altın kuralı ve güvenli bir ekip iş akışıyla anlatılıyor.
Makaleyi okuyun →Yazılım geliştirmePython Liste Üreteci (List Comprehension): Sözdizimi, Örnekler ve Kaçınılacak Durumlar
Python list comprehension anlatımı: sözdizimi, filtreleme, if-else, iç içe döngüler, ölçülmüş süreler ve düz for döngüsünün daha iyi olduğu durumlar.
Makaleyi okuyun →Veritabanları ve SQLSQL JOIN Örneklerle Açıklama (Inner, Left, Right, Full)
SQL JOIN'leri örnek tablolar ve sorgularla adım adım öğrenin: INNER, LEFT, RIGHT, FULL, CROSS ve SELF; yaygın hatalar ve performans ipuçları.
Makaleyi okuyun →