This is a memo of O'Reilly Japan's book effective python. https://www.oreilly.co.jp/books/9784873117560/ P42~44
** Consider a function that saves a log of debug information **
def log(massage, values):
if not values:
print(massage)
else:
values_str = ', '.join(str(x) for x in values)
print('%s: %s' % (massage, values_str))
log('My numbers are', [1, 2])
log('Hi there', [])
>>>
My numbers are: 1, 2
Hi there
In this case, the parameter of the log function should be given a list if there is a number, but an empty list should be given even if there is no number. I want to save this trouble, and if there is no number, I want to give no argument
Therefore, we introduce a variable-length argument called ** star argument ** with the `` `* ``` operator prepended to the argument.
def log2(massage, *values):
if not values:
print(massage)
else:
values_str = ', '.join(str(x) for x in values)
print('%s: %s' % (massage, values_str))
log2('My numbers are', [1, 2])
log2('Hi there') #No input for the second argument
>>>
My numbers are: [1, 2]
Hi there
By setting the star argument as an argument, it processes any input and considers it absent. (If you do not make it a star argument, it will not match the number of parameters of the function and will cause a TypeError)
Also, if you already have a list, you can add the `*`
operator to the list and give it to the function parameters.
favorites = [7, 33, 99]
massage = 'Favorite colors'
log2(massage, *favorites)
>>>
Favorite colors: 7, 33, 99
** 1. Variadic arguments are converted to tuples before being passed to the function ** If the caller of the function is a generator, it iterates over all tuples, which can lead to memory crashes (especially when there is a lot of data).
def my_generator():
for i in range(10):
yield i
def my_func(*args): #Here the arguments are converted to tuples
print(args)
it = my_generator() #Generator it is generated
my_func(*it) #The generator converted to tuple is output
>>>
(0, 1, 2, 3, 4, 5, 6, 7, 8, 9)
It is desirable that the number of argument lists accepted by the my_func function is small.
** 2. If the position of the variable length argument and the position of the argument at the time of calling deviate, the output will be corrupted **
def log3(sequence, message, *values):
if not values:
print('%s: %s' %(sequence, massage))
else:
value_set = ', '.join(str(x) for x in values)
print('%s: %s: %s' % (sequence, massage, value_set))
log3(1, 'Favorotes', 7, 33)
log3('Favorites', 7, 33)
>>>
1: Favorotes: 7, 33
Favorites: 7: 33
In this case, in the first output, 7 and 33 are processed correctly because the third and subsequent arguments correspond to the function log3 variadic. On the other hand, in the second output, 7 is used as a parameter for massage. And in this case, no exception will occur, and it may be left unnoticed. To get rid of this, you need to pay attention to the position of the input arguments and the parameters of the function.
Recommended Posts