Skip to content

ይህ ትምህርት ገና ወደ አማርኛ አልተተረጎመም፤ ስለዚህ በእንግሊዝኛ ቀርቧል። የእንግሊዝኛውን ገጽ ክፈቱ

*args and **kwargs

3 min read

print takes one value, or two, or ten. The functions you've written so far take an exact number of arguments. By the end of this lesson you'll write functions that accept any number, collect keyword arguments into a dict, and spread a list or dict back out into a call.

Any number of arguments

A star before a parameter collects the arguments. Predict what args is:

ውጤቱን ገምቱ

Decide before you look. Guessing wrong is how this sticks.

def total(*args):
    print(args)

total(120, 80, 45)
Pick the output

Python prints

(120, 80, 45)

*args collects every positional argument into one tuple, so printing it shows parentheses. It's one value holding three numbers, not three values.

gathers the positional arguments into a tuple (lesson 4.3), so you can loop over it, sum it, or ask its len. With no arguments it's an empty tuple, (). The name args is only a convention; the star does the work, and *prices would read better here.

def total(*prices):
    print(type(prices))
    return sum(prices)

print(total(120, 80, 45))
print(total())

In the editor, press Escape then Tab to move on.

Now total works for three prices or none. The catch is that it wants separate arguments. Hand it a list and the list becomes one item of the tuple:

ጥያቄ

In def total(*args), called as total(1, 2), what type is args?

Any number of keyword arguments

Two stars collect keyword arguments instead, into a dict: each argument's name becomes a key and its value the value. A receipt can then take whatever the customer ordered:

def receipt(**kwargs):
    for item, price in kwargs.items():
        print(f"{item}: {price} birr")
    print(f"Total: {sum(kwargs.values())} birr")

receipt(coffee=40, bread=25, tea=15)

In the editor, press Escape then Tab to move on.

("keyword arguments") keeps the order you passed them in, as dicts do.

Spreading values into a call

The stars work the other way in a call. * before a list spreads its items out as separate positional arguments, and ** before a dict spreads it out as keyword arguments. This is . Compare the two prints:

items = ["coffee", "bread", "tea"]
print(items)
print(*items)

In the editor, press Escape then Tab to move on.

The first print gets one list. The second gets three strings, as if you'd written print("coffee", "bread", "tea"). A dict's keys must match the parameter names:

def fare(km, base=20, per_km=5):
    return base + km * per_km

options = {"km": 10, "per_km": 8}
print(fare(**options))

In the editor, press Escape then Tab to move on.

That's fare(km=10, per_km=8), so base keeps its default.

When to use them

Stars are for helpers that really take "any number": a total, an average, a function that passes its arguments on to another. Most functions shouldn't use them. With def fare(km, base=20, per_km=5), the def line tells a reader exactly what to pass, and a typo like per_kn=8 is an error instead of a key nobody reads. Reach for *args when the count really varies, not to avoid naming parameters.

መልመጃ

An average of any number of scores

Write average(*scores) returning the average of the scores. With no scores it should return 0 instead of crashing (dividing by len(scores), which is 0, would be a ZeroDivisionError).

Output
79.0
0

Your code

def average(*scores):
    # Return 0 when there are no scores
    return sum(scores) / len(scores)

print(average(80, 90, 67))
print(average())

In the editor, press Escape then Tab to move on.

መፍትሄውን አሳይ

This is one way to solve it, not the only one. If yours prints the same thing, it works.

def average(*scores):
    if len(scores) == 0:
        return 0
    return sum(scores) / len(scores)

print(average(80, 90, 67))
print(average())

ዋና ዋና ነጥቦች

  • *args collects any number of positional arguments into a tuple.
  • **kwargs collects any number of keyword arguments into a dict.
  • In a call, *items spreads a list into separate arguments, and **options spreads a dict into keyword arguments.
  • Passing a list to *args gives a tuple holding one list; spread it with * instead.
  • Use stars when the count really varies; name your parameters everywhere else.