Article Directory
List comprehension
format:
list1 = [The expression that generates the element for the element of the original list in the original list if the conditions that need to be met]
use:
The following code is an example, you can see that the square of all even elements in list0 is stored in the final list1.
The process of its operation is to take out the variable i of the elements from list0 one by one, and then determine whether i is divisible by 2. If it is divisible, execute the initial expression, i * i, and then put this element in the new list
It can be seen as, the list comprehension is to derive a new list from the old list
list0 = [2, 5, 6, 7, 4]
list1 = [i * i for i in list0 if i % 2 == 0]
print(list1)
'''
输出:
[4, 36, 16]
'''
There are many other uses of list comprehensions. Here are a few examples:
Use ternary operators
list0 = [2, 5, 6, 7, 4]
list1 = [i * i if i % 2 else -i for i in list0]
print(list1)
'''
输出:
[-2, 25, -6, 49, -4]
'''
# 这里Py的非零整数就是True,零就是False
Operate on string elements
list0 = ['abc', 'ccc', 'here', 'cute']
list1 = [i * 5 for i in list0 if len(i) > 3]
print(list1)
'''
输出:
['hereherehereherehere', 'cutecutecutecutecute']
'''
Filter list elements
list0 = ['abc', 'ccc', 3, 'here', 'cute', 5, True, False]
list1 = [i for i in list0 if isinstance(i, str)]
print(list1)
'''
输出:
['abc', 'ccc', 'here', 'cute']
'''
Operate on dictionary elements
list0 = [{
'key': 10}, {
'key': 34}, {
'key': 66}]
list1 = [i for i in list0 if i['key'] <= 10]
print(list1)
'''
输出:
[{'key': 10}]
'''
Loop nesting
list1 = [(i, j) for i in range(5) if i % 2 for j in range(5) if j % 2 == 0]
print(list1)
'''
输出:
[(1, 0), (1, 2), (1, 4), (3, 0), (3, 2), (3, 4)]
'''
List comprehension is faster than traversing the list one by one and adding a new list.
Set comprehension
In fact, it is the same as the list comprehension, except that there is more to remove the duplication.
set1 = {
i % 2 for i in range(10)}
print(set1)
''''
输出:
{0, 1}
''''
Dictionary comprehension
The same as the list comprehension, but it will be overwritten according to the key, and the generated value will replace the first generated value
dict0 = {
'aaa': 233, 'bbb': 332, 'ddd': 555}
dict1 = {
key: value + 5 for key, value in dict0.items()}
print(dict1)
'''
输出:
{'aaa': 238, 'bbb': 337, 'ddd': 560}
'''
Reversing the key and value
can find that if there is a duplicate key after the reversal, the value will be replaced
dict0 = {
'aaa': 233, 'bbb': 233, 'ddd': 555}
dict1 = {
value: key for key, value in dict0.items()}
print(dict1)
'''
输出:
{233: 'bbb', 555: 'ddd'}
'''
Builder
Generator-expression
If the symbol of the above list comprehension is replaced with parentheses, then the newly generated generator is a generator:
as can be seen from the following code, list is no longer a list, but a generator object, of course it can still Force it to be converted into a list
list1 = (i * i for i in range(6))
print(list1)
'''
输出:
<generator object <genexpr> at 0x0000013E4C03F5C8>
'''
At this point, if you want to get the element, you need to use the next method
generator = (i * i for i in range(6))
print(generator.__next__()) # 使用自带的__next__()方法来返回下一个元素
print(generator.__next__())
'''
输出:
0
1
'''
generator = (i * i for i in range(6))
print(next(generator))# 使用系统自带的next函数
print(next(generator))
print(next(generator))
'''
输出:
0
1
4
'''
It should be noted that the two types of next only return the next element each time, and cannot skip an element or return from any point, and the generator is of an iterable type.
Traversal generator
generator = (i * i for i in range(6))
for i in generator:
print(i)
'''
输出:
0
1
4
9
16
25
'''
Use map mapping
generator = (i * i for i in range(6))
print(list(map(lambda x: x * x, generator)))
'''
输出:
[0, 1, 16, 81, 256, 625]
'''
Generator-function
Using expressions can only create simple expressions. If it is a little more complicated, you need to use functions.
yield keyword
Through the following code, you can see that after the yield keyword is added to the function, the function becomes a generator
def generator(n: int):
cnt = 1
while cnt < n:
cnt += n
yield cnt
print(generator(5))
'''
输出:
<generator object generator at 0x0000024845B154C8>
'''
You can know the general process of the program from the following code (it is recommended to debug to see the process again)
- ge obtained the address of the generator object, but did not execute the code inside the generator
- Execute the first next, start executing the internal code, first execute the outermost initialization cnt, then enter the loop, until the yield keyword is executed, cnt is returned as the value obtained at the time, and then the internal execution of the generator stops
- Execute the second next, you can find that after printing'yield', it means that the second execution is executed after the last time the yield ended.
def generator(n: int):
cnt = 1
print("进入生成器")
while cnt < n:
cnt += 1
print("yield之前")
yield cnt
print("yield后")
ge = generator(5)
print("得到生成器----开始获取元素", end='\n\n\n')
print(ge.__next__())
print("第一个元素获取完毕", end='\n\n\n')
print(ge.__next__())
print("第二个元素获取完毕", end='\n\n\n')
'''
输出:
得到生成器----开始获取元素
进入生成器
yield之前
2
第一个元素获取完毕
yield后
yield之前
3
第二个元素获取完毕
'''
It is concluded that the variable after the yield will be returned as a value, and after encountering the yield, the code inside the generator will stop executing until the next next is called. Give another example:
def generator(n: int):
cnt = 1
print("进入生成器")
cnt += 1
yield cnt
yield 23333
ge = generator(5)
print(ge.__next__())
print(ge.__next__())
'''
输出:
进入生成器
2
23333
'''
You can think of yield as a special return, but the current iterator will not end after execution. In fact, yield can be used without the returned value so that yield can be used as a suspended tool.
Function generator and return
Executing the following code will cause an exception, because the current generator can only generate two elements, but it has executed three next
def generator(n: int):
cnt = 1
cnt += 1
yield cnt
yield 23333
ge = generator(5)
print(ge.__next__())
print(ge.__next__())
print(ge.__next__())
'''
輸出:
2
23333
Traceback (most recent call last):
File "D:\Pycharm\Project\Pytest\test.py", line 11, in <module>
print(ge.__next__())
StopIteration
'''
If you add a return here, you can find that the value of return is output as an abnormal message
def generator(n: int):
cnt = 1
cnt += 1
yield cnt
yield 23333
return "生成器结束"
ge = generator(5)
print(ge.__next__())
print(ge.__next__())
print(ge.__next__())
'''
输出:
Traceback (most recent call last):
2
File "D:\Pycharm\Project\Pytest\test.py", line 12, in <module>
23333
print(ge.__next__())
StopIteration: 生成器结束
'''
send method
Use the send method on the generator, you can pass in a value to the generator, and also get the return element of the generator, so that the generator can communicate with the outside world
The information sent when using send is equivalent to the value of yield, so use a variable to receive the value of yield.
Note that you can only pass None when you first use send, otherwise an error will be reported.
The reason is very simple. After analyzing the execution process of the generator above, it can be known that when the generator is executed for the first time, the execution ends when the yield is executed, that is, there is no opportunity for the yield to receive the value, so the value will be reported as an error.
It is recommended to debug the understanding process
def generator(n: int):
cnt = 1
while cnt < n:
cnt += 1
message = yield cnt
print(message)
ge = generator(5)
print(ge.send(1005))
'''
输出:
Traceback (most recent call last):
File "D:\Pycharm\Project\Pytest\test.py", line 10, in <module>
print(ge.send(1005))
TypeError: can't send non-None value to a just-started generator
'''
use correctly:
def generator(n: int):
cnt = 1
while cnt < n:
cnt += 1
message = yield cnt
print(message)
ge = generator(5)
print(ge.send(None))
print(ge.send(1005))
print(ge.send(1005))
'''
输出:
2
1005
3
1005
4
'''
You can also:
def generator(n: int):
cnt = 1
while cnt < n:
cnt += 1
message = yield cnt
print(message)
ge = generator(5)
print(ge.__next__())
print(ge.send(1005))
print(ge.send(1005))
'''
输出:
2
1005
3
1005
4
'''
In short, the yield must be executed once before using send to send non-None messages.