解析式_迭代器

解析式

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 之間的任意整數轉化爲羅馬數字
相關文章
相關標籤/搜索