2.15. Argumentumok¶
Egy függvényt többféleképpen lehet meghívni, és a paraméterei is többféle formában deklarálhatók. A kombinációk elsőre ijesztőnek tűnnek; a gyakorlatban három-négy minta szinte mindent lefed.
2.15.1. Pozicionális és kulcsszavas argumentumok¶
A legegyszerűbb hívás pozíció szerint adja át az argumentumokat – az első érték az első paraméterhez kerül, a második a másodikhoz, és így tovább:
def rect(x, y, w, h):
return (x, y, w, h)
rect(10, 20, 100, 50)
Ugyanaz a hívás kulcsszó szerint is átadhatja az argumentumokat, mindegyik paramétert explicit módon megnevezve:
rect(x=10, y=20, w=100, h=50)
A kulcsszavas argumentumok sorrendtől függetlenek, és önmagukat dokumentálóvá teszik a hívásokat, cserébe több gépelésért. A pozicionális és kulcsszavas argumentumok keveredhetnek egyetlen hívásban, de minden pozicionálisnak meg kell előznie bármely kulcsszavast:
rect(10, 20, w=100, h=50) # OK
rect(x=10, 20, 100, 50) # SyntaxError
2.15.2. Alapértelmezett értékek¶
Egy paraméter deklarálhat alapértelmezett értéket, amelyet akkor használ, ha a hívó nem ad meg egyet:
def greet(name, greeting="hello"):
print(greeting, name)
greet("Alice") # hello Alice
greet("Alice", "hi") # hi Alice
greet("Alice", greeting="hey") # hey Alice
Az alapértelmezett értékkel rendelkező paramétereknek az alapértelmezett érték nélküliek után kell állniuk a def sorban.
Figyelem
Az alapértelmezett értékek egyszer kerülnek kiértékelésre, amikor a def lefut – nem minden híváskor. Egy módosítható alapértelmezett ([], {}) használata azt eredményezi, hogy ugyanazt az objektumot osztja meg minden olyan hívás, amely az alapértelmezettet veszi át. Helyette használj None értéket őrszemként:
def append_to(item, target=None):
if target is None:
target = []
target.append(item)
return target
2.15.3. Változó hosszúságú: *args és **kwargs¶
A * előtaggal ellátott paraméter az összes megmaradt pozicionális argumentumot egy tuple típusba gyűjti. A ** előtaggal ellátott paraméter az összes megmaradt kulcsszavas argumentumot egy dict típusba gyűjti. A szokásos nevek az args és a kwargs, de bármely azonosító működik:
def report(label, *values, **options):
print(label, values, options)
report("temps", 21, 22, 23, unit="C", precision=1)
Kimenet:
temps (21, 22, 23) {'unit': 'C', 'precision': 1}
Egy függvénynek ritkán van szüksége mindkettőre. A leggyakoribb felhasználás az argumentumok továbbítása egy burkolóból egy belső hívásba:
def log_and_call(func, *args, **kwargs):
print("calling", func.__name__)
return func(*args, **kwargs)
A hívás helyén lévő tükörkép-szintaxis egy iterálható objektumot pozicionális argumentumokká (*) vagy egy dict típust kulcsszavas argumentumokká (**) csomagol ki:
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. Csak kulcsszavas paraméterek¶
Egy önállóan álló * a paraméterlistában (névhez nem kapcsolva) minden őt követő paramétert csak kulcsszavassá tesz – a hívónak a nevet kell használnia:
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
Ezt logikai jelzőkhöz és más olyan argumentumokhoz használd, ahol egy puszta érték a hívás helyén nem lenne magától értetődő.