解析式_迭代器

解析式

In [2]: lst = list(range(10))

In [3]: ret = []

In [4]: for x in lst:
   ...:     ret.append(x ** 2)
   ...:     

In [5]: ret
Out[5]: [0, 1, 4, 9, 16, 25, 36, 49, 64, 81]

In [6]: ret = [x ** 2 for x in lst]

In [7]: ret
Out[7]: [0, 1, 4, 9, 16, 25, 36, 49, 64, 81]

In [8]:

1、列表解析式

语法:[expr for e in iterator]python

优势:缓存

  • 代码简洁,可读性强
  • 效率比 普通迭代稍高, 并非数量级的提高
In [8]: %%timeit
   ...: lst = list(range(100000))
   ...: ret = []
   ...: for x in lst:
   ...:     ret.append(x ** 2)
   ...: 
34.9 ms ± 421 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)


In [9]: %%timeit
   ...: lst = list(range(100000))
   ...: ret = [x ** 2 for x in lst]
   ...: 
29.6 ms ± 341 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)

In [10]:
In [10]: ret = []

In [11]: for x in lst:
    ...:     if x % 2 == 0:
    ...:         ret.append(x)
    ...:         

In [12]: ret
Out[12]: [0, 2, 4, 6, 8]

In [13]: ret = [x for x in lst if x > 0 and x < 5]

In [14]: ret
Out[14]: [1, 2, 3, 4]

In [15]: 

In [15]: ret = [x for x in lst if x < 5 or x > 7 if x % 2 == 0]

In [16]: ret
Out[16]: [0, 2, 4, 8]

In [17]:
In [18]: [(x, y) for x in range(5) for y in range(5, 10)]
Out[18]: 
[(0, 5),
 (0, 6),
 (0, 7),
 (0, 8),
 (0, 9),
 (1, 5),
 (1, 6),
 (1, 7),
 (1, 8),
 (1, 9),
 (2, 5),
 (2, 6),
 (2, 7),
 (2, 8),
 (2, 9),
 (3, 5),
 (3, 6),
 (3, 7),
 (3, 8),
 (3, 9),
 (4, 5),
 (4, 6),
 (4, 7),
 (4, 8),
 (4, 9)]

In [19]: 

In [19]: ret = []

In [20]: for x in range(5):
    ...:     for y in range(5, 10):
    ...:         ret.append((x, y))
    ...:         

In [21]: ret
Out[21]: 
[(0, 5),
 (0, 6),
 (0, 7),
 (0, 8),
 (0, 9),
 (1, 5),
 (1, 6),
 (1, 7),
 (1, 8),
 (1, 9),
 (2, 5),
 (2, 6),
 (2, 7),
 (2, 8),
 (2, 9),
 (3, 5),
 (3, 6),
 (3, 7),
 (3, 8),
 (3, 9),
 (4, 5),
 (4, 6),
 (4, 7),
 (4, 8),
 (4, 9)]

In [22]:
ret = []
for x in range(5):
    for y in range(5, 10):
        for z in range(10, 15):

In [23]: ret = [(x, y, z) for x in range(5) for y in range(5, 10) for z in range(10, 15)]

In [24]: ret
Out[24]: 
[(0, 5, 10),
 (0, 5, 11),
 (0, 5, 12),
 (0, 5, 13),
 (0, 5, 14),
 (0, 6, 10),
 (0, 6, 11),
 (0, 6, 12),
 (0, 6, 13),
 (0, 6, 14),
 (0, 7, 10),
 (0, 7, 11),
 (0, 7, 12),
 (0, 7, 13),
 (0, 7, 14),
 (0, 8, 10),
 (0, 8, 11),
 (0, 8, 12),
 (0, 8, 13),
 (0, 8, 14),
 (0, 9, 10),
 (0, 9, 11),
 (0, 9, 12),
 (0, 9, 13),
 (0, 9, 14),
 (1, 5, 10),
 (1, 5, 11),
 (1, 5, 12),
 (1, 5, 13),
 (1, 5, 14),
 (1, 6, 10),
 (1, 6, 11),
 (1, 6, 12),
 (1, 6, 13),
 (1, 6, 14),
 (1, 7, 10),
 (1, 7, 11),
 (1, 7, 12),
 (1, 7, 13),
 (1, 7, 14),
 (1, 8, 10),
 (1, 8, 11),
 (1, 8, 12),
 (1, 8, 13),
 (1, 8, 14),
 (1, 9, 10),
 (1, 9, 11),
 (1, 9, 12),
 (1, 9, 13),
 (1, 9, 14),
 (2, 5, 10),
 (2, 5, 11),
 (2, 5, 12),
 (2, 5, 13),
 (2, 5, 14),
 (2, 6, 10),
 (2, 6, 11),
 (2, 6, 12),
 (2, 6, 13),
 (2, 6, 14),
 (2, 7, 10),
 (2, 7, 11),
 (2, 7, 12),
 (2, 7, 13),
 (2, 7, 14),
 (2, 8, 10),
 (2, 8, 11),
 (2, 8, 12),
 (2, 8, 13),
 (2, 8, 14),
 (2, 9, 10),
 (2, 9, 11),
 (2, 9, 12),
 (2, 9, 13),
 (2, 9, 14),
 (3, 5, 10),
 (3, 5, 11),
 (3, 5, 12),
 (3, 5, 13),
 (3, 5, 14),
 (3, 6, 10),
 (3, 6, 11),
 (3, 6, 12),
 (3, 6, 13),
 (3, 6, 14),
 (3, 7, 10),
 (3, 7, 11),
 (3, 7, 12),
 (3, 7, 13),
 (3, 7, 14),
 (3, 8, 10),
 (3, 8, 11),
 (3, 8, 12),
 (3, 8, 13),
 (3, 8, 14),
 (3, 9, 10),
 (3, 9, 11),
 (3, 9, 12),
 (3, 9, 13),
 (3, 9, 14),
 (4, 5, 10),
 (4, 5, 11),
 (4, 5, 12),
 (4, 5, 13),
 (4, 5, 14),
 (4, 6, 10),
 (4, 6, 11),
 (4, 6, 12),
 (4, 6, 13),
 (4, 6, 14),
 (4, 7, 10),
 (4, 7, 11),
 (4, 7, 12),
 (4, 7, 13),
 (4, 7, 14),
 (4, 8, 10),
 (4, 8, 11),
 (4, 8, 12),
 (4, 8, 13),
 (4, 8, 14),
 (4, 9, 10),
 (4, 9, 11),
 (4, 9, 12),
 (4, 9, 13),
 (4, 9, 14)]

In [25]:

何时用列表解析式?数据结构

  • 跟着感受走
  • 太复杂,须要转换的,就写for循环
  • 多个for循环,明显不知道结果是什么的,就不要用了
  • 一眼看不出解析式的结果是什么,也不要用了
# 偶数求平方, 奇数求立方
In [27]: ret = []

In [28]: for x in lst:
    ...:     if x % 2 == 0:
    ...:         ret.append(x ** 2)
    ...:     else:
    ...:         ret.append(x ** 3)
    ...:             

In [29]: ret
Out[29]: [0, 1, 4, 27, 16, 125, 36, 343, 64, 729]

In [30]:
In [30]: ret = x ** 2 if x * 2 == 0 else x ** 3  # 三元表达式, 三目表达式

# 语法:  ret = x if cond else y
# 偶数求平方, 奇数求立方
In [33]: ret = []

In [34]: for x in lst:
    ...:     ret = [x ** 2 if x % 2 == 0 else x ** 3 for x in lst]
    ...:     

In [35]: ret
Out[35]: [0, 1, 4, 27, 16, 125, 36, 343, 64, 729]

In [36]:
In [37]: 3 if True  else 4
Out[37]: 3

In [38]: 3 if True    # Python中 三元表达式, 必需要有else,且只能有一个 if... else
  File "<ipython-input-38-20b69ec8c953>", line 1
    3 if True
             ^
SyntaxError: invalid syntax


In [39]:

2、生成器解析式

In [40]: g = (x ** 2 for x in range(100))  # 使用一对圆括号 代替以前的 方括号,这就变成了 生成器解析式

In [41]: g
Out[41]: <generator object <genexpr> at 0x7f1935b64a98>

In [42]:

生成器解析式,返回的是一个生成器app

优势: 不占内存, 惰性求值函数

In [42]: def fn(x):
    ...:     print('executed')
    ...:     return x
    ...: g = (fn(x) for x in range(10))
    ...: 

In [43]:

何时使用生成器?oop

  • 明确知道使用下标的时候,用列表解析式,由于生成器是没法使用下标进行访问的
  • 若是咱们用缓存,就不能用生成器解析式了,就要用列表解析式了

3、集合解析式

In [46]: { x for x in range(10)}     # 使用 {} 替换以前的 方括号
Out[46]: {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}

In [47]: s = {x for x in range(10)}  # 返回的是一个 set

In [48]: type(s)
Out[48]: set

In [49]:

4、字典解析

In [50]: {str(x): x for x in range(10)}  # key 和 value 之间须要用 冒号 进行分割。
Out[50]: 
{'0': 0,
 '1': 1,
 '2': 2,
 '3': 3,
 '4': 4,
 '5': 5,
 '6': 6,
 '7': 7,
 '8': 8,
 '9': 9}

In [51]: d = {}

In [52]: for x in range(10):
    ...:     d[str(x)] = x
    ...:     

In [53]: d
Out[53]: 
{'0': 0,
 '1': 1,
 '2': 2,
 '3': 3,
 '4': 4,
 '5': 5,
 '6': 6,
 '7': 7,
 '8': 8,
 '9': 9}

In [54]: {str(x): x ** 2 for x in range(10)}
Out[54]: 
{'0': 0,
 '1': 1,
 '2': 4,
 '3': 9,
 '4': 16,
 '5': 25,
 '6': 36,
 '7': 49,
 '8': 64,
 '9': 81}

可迭代对象 和 迭代器

In [55]: r = range(10)

In [56]: r.__iter__
Out[56]: <method-wrapper '__iter__' of range object at 0x7f1934f28810>

In [57]: s = '123'

In [58]: s.__iter__
Out[58]: <method-wrapper '__iter__' of str object at 0x7f1934e503e8>

In [59]: i = 1

In [60]: i.__iter__
---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
<ipython-input-60-c79eb23e70cf> in <module>()
----> 1 i.__iter__

AttributeError: 'int' object has no attribute '__iter__'

In [61]:

有__iter__方法的对象叫作 可迭代对象。spa

In [62]: for x in range(10):
    ...:     pass
    ...: 

In [63]: b = b'abc'

In [64]: b[0]
Out[64]: 97

In [65]:

哪些数据结构是可迭代对象:code

  • list
  • set
  • tuple
  • dict
  • str
  • bytearray
  • bytes

迭代器是可迭代对象, 可迭代对象不必定是迭代器对象

In [68]: it = iter(range(10))  # 咱们能够经过 iter() 将可将迭代对象转换为 迭代器

In [69]: it.__next__()
Out[69]: 0

In [70]: it.__next__()
Out[70]: 1

In [71]: it.__iter__
Out[71]: <method-wrapper '__iter__' of range_iterator object at 0x7f1935968ea0>

In [72]:

有__next__方法的,咱们称为 迭代器ip

In [72]: lst = [['m', 1, 2, 3, 4], ['age', 1, 2, 3]]

In [73]: for x in lst:
    ...:     key = x[0]
    ...:     for v in x[1:]:
    ...:         print(v)
    ...:         
1
2
3
4
1
2
3

In [74]: for x in lst:
    ...:     it = iter(x)
    ...:     key = next(it)
    ...:     for v in it:
    ...:         print(v)
    ...:         
1
2
3
4
1
2
3

In [75]:

for in 循环对于可迭代对象:

  • 首先调用 iter 方法转化为迭代器
  • 而后不断的调用next方法
  • 直接抛出 StopIteration异常
it = iter(iterable)
while True:
    try:
        next(it)
    except StopIteration:
        return

做业:

  • 1. 把字符串形式的整数或浮点数转化为int 或者float,**不是int 和 float 函数**

    提示: 可使用字典

  • 2. 移出列表中的重复元素,并保持新列表和原列表的顺序一致
  • 3. 统计文本中各单词出现的次数
  • 4. 把1-4000 之间的任意整数转化为罗马数字
相关文章
相关标签/搜索