I saw this code online. And this prints a left aligned pyramid using "*"
height = 5
for row in range(1, height+ 1):
print(" " * (height - row) +"*" * row)
In the " " * (height - row), what does the asterisk do? It's not between quotation marks so I think it multiplies " " and (height - row)? But idk since " " is not a number.
The *args and **kwargs are common idioms to allow an arbitrary number of arguments to functions, as described in the section more on defining functions in the Python tutorial.
The *args will give you all positional arguments as a tuple:
Copydef foo(*args):
for a in args:
print(a)
foo(1)
# 1
foo(1, 2, 3)
# 1
# 2
# 3
The **kwargs will give you all
keyword arguments as a dictionary:
Copydef bar(**kwargs):
for a in kwargs:
print(a, kwargs[a])
bar(name='one', age=27)
# name one
# age 27
Both idioms can be mixed with normal arguments to allow a set of fixed and some variable arguments:
Copydef foo(kind, *args, bar=None, **kwargs):
print(kind, args, bar, kwargs)
foo(123, 'a', 'b', apple='red')
# 123 ('a', 'b') None {'apple': 'red'}
It is also possible to use this the other way around:
Copydef foo(a, b, c):
print(a, b, c)
obj = {'b':10, 'c':'lee'}
foo(100, **obj)
# 100 10 lee
Another usage of the *l idiom is to unpack argument lists when calling a function.
Copydef foo(bar, lee):
print(bar, lee)
baz = [1, 2]
foo(*baz)
# 1 2
In Python 3 it is possible to use *l on the left side of an assignment (Extended Iterable Unpacking), though it gives a list instead of a tuple in this context:
Copyfirst, *rest = [1, 2, 3, 4]
# first = 1
# rest = [2, 3, 4]
Also Python 3 adds a new semantic (refer PEP 3102):
Copydef func(arg1, arg2, arg3, *, kwarg1, kwarg2):
pass
Such function accepts only 3 positional arguments, and everything after * can only be passed as keyword arguments.
Note:
A Python dict, semantically used for keyword argument passing, is arbitrarily ordered. However, in Python 3.6+, keyword arguments are guaranteed to remember insertion order.
"The order of elements in **kwargs now corresponds to the order in which keyword arguments were passed to the function." - What’s New In Python 3.6.
In fact, all dicts in CPython 3.6 will remember insertion order as an implementation detail, and this becomes standard in Python 3.7.
It's also worth noting that you can use * and ** when calling functions as well. This is a shortcut that allows you to pass multiple arguments to a function directly using either a list/tuple or a dictionary. For example, if you have the following function:
Copydef foo(x,y,z):
print("x=" + str(x))
print("y=" + str(y))
print("z=" + str(z))
You can do things like:
Copy>>> mylist = [1,2,3]
>>> foo(*mylist)
x=1
y=2
z=3
>>> mydict = {'x':1,'y':2,'z':3}
>>> foo(**mydict)
x=1
y=2
z=3
>>> mytuple = (1, 2, 3)
>>> foo(*mytuple)
x=1
y=2
z=3
Note: The keys in mydict have to be named exactly like the parameters of function foo. Otherwise it will throw a TypeError:
Copy>>> mydict = {'x':1,'y':2,'z':3,'badnews':9}
>>> foo(**mydict)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: foo() got an unexpected keyword argument 'badnews'