2.15. Argumentit

Funktiota voidaan kutsua usealla tavalla, ja sen parametrit voidaan määritellä useassa muodossa. Yhdistelmät vaikuttavat aluksi pelottavilta; kolme tai neljä kaavaa kattaa käytännössä lähes kaiken.

2.15.1. Sijainti- ja avainsana-argumentit

Yksinkertaisin kutsu välittää argumentit sijainnin mukaan – ensimmäinen arvo menee ensimmäiseen parametriin, toinen toiseen ja niin edelleen:

def rect(x, y, w, h):
    return (x, y, w, h)

rect(10, 20, 100, 50)

Sama kutsu voi välittää argumentit avainsanan mukaan nimeämällä kunkin parametrin nimenomaisesti:

rect(x=10, y=20, w=100, h=50)

Avainsana-argumentit ovat järjestyksestä riippumattomia ja tekevät kutsuista itsensä dokumentoivia hieman suuremman kirjoittamismäärän hinnalla. Sijainti- ja avainsana-argumentit voivat sekoittua yhdessä kutsussa, mutta jokaisen sijaintiargumentin täytyy esiintyä ennen mitään avainsana-argumenttia:

rect(10, 20, w=100, h=50)         # OK
rect(x=10, 20, 100, 50)           # SyntaxError

2.15.2. Oletusarvot

Parametri voi määritellä oletusarvon, jota käytetään, kun kutsuja ei anna omaansa:

def greet(name, greeting="hello"):
    print(greeting, name)

greet("Alice")                    # hello Alice
greet("Alice", "hi")              # hi Alice
greet("Alice", greeting="hey")    # hey Alice

Oletusarvolliset parametrit täytyy sijoittaa def-rivillä jälkeen niiden parametrien, joilla ei ole oletusarvoa.

Varoitus

Oletusarvot lasketaan kerran, kun def suoritetaan – ei jokaisella kutsulla. Muuttuvan oletusarvon ([], {}) käyttäminen aiheuttaa sen, että sama objekti jaetaan kaikkien oletusarvoa käyttävien kutsujen kesken. Käytä sen sijaan None-arvoa vartijana:

def append_to(item, target=None):
    if target is None:
        target = []
    target.append(item)
    return target

2.15.3. Vaihteleva pituus: *args ja **kwargs

*-etuliitteellä varustettu parametri kerää kaikki yli jääneet sijaintiargumentit tuple-monikkoon. **-etuliitteellä varustettu parametri kerää kaikki yli jääneet avainsana-argumentit dict-sanakirjaan. Tavanomaiset nimet ovat args ja kwargs, mutta mikä tahansa tunniste käy:

def report(label, *values, **options):
    print(label, values, options)

report("temps", 21, 22, 23, unit="C", precision=1)

Tuloste:

temps (21, 22, 23) {'unit': 'C', 'precision': 1}

Funktio tarvitsee harvoin molempia. Yleisin käyttö on argumenttien välittäminen kääreestä sisäiseen kutsuun:

def log_and_call(func, *args, **kwargs):
    print("calling", func.__name__)
    return func(*args, **kwargs)

Peilikuvasyntaksi kutsun paikalla purkaa iteroitavan sijaintiargumenteiksi (*) tai dict-sanakirjan avainsana-argumenteiksi (**):

point = (10, 20, 100, 50)
rect(*point)                      # same as rect(10, 20, 100, 50)

kwargs = {"x": 10, "y": 20, "w": 100, "h": 50}
rect(**kwargs)                    # same as rect(x=10, y=20, ...)

2.15.4. Vain avainsanalla annettavat parametrit

Pelkkä * parametriluettelossa (ei kiinnitettynä nimeen) merkitsee jokaisen sitä seuraavan parametrin vain avainsanalla annettavaksi – kutsujan täytyy käyttää nimeä:

def crop(buffer, *, x, y, w, h):
    ...

crop(buffer, x=0, y=0, w=100, h=100)   # OK
crop(buffer, 0, 0, 100, 100)           # TypeError

Käytä tätä totuusarvolippuihin ja muihin argumentteihin, joissa paljas arvo kutsun paikalla ei olisi itsestään selvä.