The other day I learned about 100 Days Of Code, which was popular on Twitter for a while. The purpose of this article is to keep a record and output how much I, as a beginner, can grow through 100 days of study. I think there are many mistakes and difficult to read. I would appreciate it if you could point out!
--Progress: Pages 38-48 ――I will write down what I often forget or didn't know about what I learned today.
--If iterates with an iterator or generator and the StopIteration exception has already occurred, iterating again will not produce any results.
numbers = [1, 2, 3, 4, 5]
def iter_square(numbers):
for number in numbers:
yield number ** 2
iter = iter_square(numbers)
for x in iter:
print(x)
#No output for the second for statement due to a StopIteration exception
for x in iter:
print(x)
Output result
1
4
9
16
25
Iterating over an iterator that has already run out is very confusing as it does not cause any errors. To solve this problem, I run the input iterator until it's explicitly exhausted and copy it to the full content list. The list can be iterated over and over again, eliminating this confusion.
numbers = [1, 2, 3, 4, 5]
def iter_square(numbers):
for number in numbers:
yield number ** 2
iter = iter_square(numbers)
iter_list = list(iter)
for x in iter_list:
print(x)
for x in iter_list:
print(x)
Output result
1
4
9
16
25
1
4
9
16
25
However, since it uses a list, it may crash if the contents of the copy of the input iterator become large. To avoid this, define a new container class that implements the iterator protocol.
numbers = [1, 2, 3, 4, 5]
class SampleClass(object):
def __init__(self, numbers):
self.numbers = numbers
def __iter__(self):
for number in self.numbers
yield number
def func_square(numbers):
result = []
for value in numbers:
square_value = value ** 2
result.append(square_value)
return result
num = SampleClass(numbers)
result = func_square(num)
print(result)
--Star arguments (* args) can be used to keep function calls nesting and reduce visual noise. --The function can accept a variable number of positional arguments by using * args in the def statement. -* Operators can be used in functions to use elements from sequences as positional arguments -* When using the operator with a generator, the program may run out of memory and crash. --Adding a new position parameter to a function that accepts * args can create bugs that are difficult to find.
For example, when logging debug information, if you have a fixed number of arguments, you need a function that takes a message and a list of values.
def log(message, values):
if not values:
print(message)
else:
values_str = ', '.join(str(x) for x in values)
print('%s: %s' % (message, values_str))
log('MY numbers are', [1, 2])
log('Hi there', [])
It's annoying to have to pass an empty list even when there is no value. In Python, it can be made optional by adding * to the name of the last positional argument.
def log(message, *values):
if not values:
print(message)
else:
values_str = ', '.join(str(x) for x in values)
print('%s: %s' % (message, values_str))
log('MY numbers are', [1, 2])
log('Hi there')
If you already have a list and want to call a variadic function like log, you can call it using the * operator.
log('HELLO', *list)
# *If you do not add, the list will be output as it is.
log('HELLO', list)
Output result
HELLO: 1, 2, 3
HELLO: [1, 2, 3]
There are two problems with variable-length positional arguments.
--Function arguments can be specified by position or keyword --Keyword arguments clarify the purpose of each argument when the positional argument alone is confusing. --Keyword arguments with default values make it easy to add new behavior to a function, even if it has already been called by others. --Optional keyword arguments should always be passed by keyword, not position
Recommended Posts