Python *args ve **kwargs’ın Açıklaması: Açık Örneklerle Esnek Fonksiyonlar

  1. Ana sayfa
  2. Blog
  3. Yazılım Geliştirme

Yazılım Geliştirme

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.

8 dk okuma
Python *args ve **kwargs'ın açıklaması: anlaşılır örneklerle esnek işlevler

Önemli noktalar

  • *args fazladan konumsal argümanları bir demet‘te toplar.
  • **kwargs fazladan 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:

  1. Düzenli konumsal parametreler
  2. *argümanlar
  3. Yalnızca anahtar kelime parametreleri
  4. **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}), burada a ilk 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 form func(*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

Stack Quora ile çalışın

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.

Okumaya devam et

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 zekâ

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 →
DevOps

Açı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ştirme

API 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 otomasyonu

Python'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 testi

Kod 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 SQL

SQL'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 SQL

Açı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ştirme

TypeScript 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ştirme

Python *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ştirme

Python 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 →
DevOps

Docker 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 otomasyonu

TDD 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ştirme

Git 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ştirme

Python 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 SQL

SQL 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 →