For example, what does * (asterisk) in the following code:

 print(*min(p for p in counter.items() if p[1] == max_count)) print(*team, *coef) seasons = [datetime(*args) for args in [ (Y, 1, 1), # winter (Y, 3, 1), # spring (Y, 6, 1), # summer (Y, 9, 1), # autumn (Y, 12, 1) # winter ]] def lcm(*args): """Least common multiple.""" return reduce(lambda a, b: a * b // gcd(a, b), args) async def watchdog(loop, last_activity_time, timeout, func, *args): "Run *func(*args)* if more than *timeout* seconds since *last_activity_time*." while (loop.time() - last_activity_time()) < timeout: await asyncio.sleep(1) return func(*args) 

and what do two ** stars do:

 '{a:.{n}f}'.format(**vars()) class A: def __init__(self, a, **kwargs): super().__init__(**kwargs) 

1 answer 1

An asterisk in Python besides multiplying x*y ( help('*') ) and raising to a power x**y ( help('**') ) † is used to denote zero or more .

For example, in the description of the parameters of the function:

 def f(*args): print(args) 

* means that the function takes zero or more arguments that are available inside the function as an args tuple:

 >>> f(1,'a') (1, 'a') 

Named parameters use two asterisks :

 def g(a, b, *args, name='default', **kwargs): print(a, b, args, name, kwargs) 

here g() takes two required arguments and an arbitrary (zero or more) number of other arguments:

 >>> g(1, b=2, c=3) 1 2 () default {'c': 3} 

kwargs is a dictionary of additional arguments passed by name ( c in this case). And args is an empty tuple () , since no additional positional arguments were passed.

After * all parameters must be passed by name, for example :

 def min_item(items, *, key=lambda x: x): ... 

When called, if specified, the key must be specified by name: min([1,2,-3], key=abs) .

Accepting an arbitrary number of arguments can be useful when creating wrapper functions:

 def my_print(*args, **kwargs): flush = kwargs.pop('flush', True) # flush unless overriden print(*args, flush=flush, **kwargs) 

With multiple inheritance **kwargs helps to implement the parameter compatibility requirement for base class methods, since kwargs allows you to pass arbitrary named arguments.

It can be seen that the asterisk can also be used when calling a function :

 L = [1, 2, 3] s = "abc" print(*L, *s) # iterable unpacking: print(1, 2, 3, 'a', 'b', 'c') # -> 1 2 3 abc 

arbitrary collections (iterable in general) L , s unpacked and each of their elements is passed as a separate argument to the called function ( print() ).

Can be used with explicit assignment:

 >>> first, *middle, last = L >>> first, middle, last (1, [2], 3) 

in this case, the first and last arguments from list L unpacked into explicitly given names ( first , last ), and the remainder zero or more elements as a list are placed in the middle .

The asterisk can also be used when defining lists, tuples, sets and dictionaries in the source code using the appropriate syntax ( tuple, list, set , and dictionary displays ):

 >>> *range(4), 4 (0, 1, 2, 3, 4) >>> [*range(4), 4] [0, 1, 2, 3, 4] >>> {*range(4), 4} {0, 1, 2, 3, 4} >>> {'x': 1, **{'y': 2}} # dictionary unpacking inside dictionary display {'x': 1, 'y': 2} 

Subtle point: a comma in Python creates a tuple — brackets are needed only for an empty tuple () . Therefore, the first line is equivalent to: (*range(4), 4) .

Just like when calling functions, the asterisk unpacks the collection here and acts as if each element was transferred separately to the appropriate constructors.

Thus, you can add two dictionaries or arbitrary mappings ( Mapping ):

 >>> a = {'a': 1, 'b': 2} >>> b = {'a': 3, 'c': 0} >>> {**a, **b} {'a': 3, 'b': 2, 'c': 0} >>> {**b, **a} {'a': 1, 'c': 0, 'b': 2} 

If there are duplicate keys, later values ​​win as usual : {'a': 1, 'a': 3} == {'a': 3} .

Knowing what an asterisk makes is useful to explain how zip(*matrix) transposes a square matrix or how to bypass an iterator exactly n elements at a time: zip(*[iterator]*n) .

In addition to the specified values, an asterisk may be present in the file name for creating a wildcard, for example :

 from pathlib import Path print(*Path().glob('*.py')) print(*Path().glob('**/*.py')) 

The first print() prints all (zero or more) file names in the current directory with the .py extension. Similar ( *.py ) syntax is popular because it is used on the command line (shell).
The second print() with two asterisks ( '**/*.py' ) displays the names of Python files in the entire directory tree (including the subdirectories).

In regular expressions * means repeating zero or more times:

 import re if re.fullmatch(r'x*', text): print('текст пустой или содержит только `x`') 

multiplication of natural numbers n*m can be considered as a repetition of addition (zero or more) times. Similarly, raising to the power of n**m can be considered as a repetition of multiplication:

  2 * 3 == 2 + 2 + 2 2 ** 3 == 2 * 2 * 2 [2] * 3 == [2, 2, 2] 

  • one
    {**a, **b} does not work in Python 3.4. Indicate which version works with. - Smit Johnth
  • one
    @SmitJohnth is possible, but also so much information in the answer. The current version of Python is already 3.6. Those who are interested in details can click on the link - the version is shown there (I’ve got that link so that anyone who has the desire can get more details). - jfs
  • one
    What, 2.7 already dug? - Smit Johnth
  • one
    @SmitJohnth the question has a python-3.x label and no python-2.7 label. If you wish, you can ask a similar question for Python 2 (there are many differences, the answer and so much material at the very top covers). - jfs
  • four
    @SmitJohnth look at the author of the question. Once again, if you are interested in something else, then ask your question (I'm sure that I know the intentions of the author of the current question). - jfs