Skip to content

Latest commit

 

History

History
256 lines (153 loc) · 4.35 KB

File metadata and controls

256 lines (153 loc) · 4.35 KB

解析式:

问题引入:

对一个列表里所有数值求平方;

lst = list(range(10))

列表解析:

之所以叫列表解析是因为得到的结果是list,迭代的对象可以是任意可迭代对象;

列表解析中,不支持break语句,自然也不支持for...else语句;

[ expression for e in iterator]

lst = list(range(10))
ret = []
for x in lst:
    ret.append(x ** 2)

ret = [ x ** 2 for x in lst]
  • 代码简介,可读性强;
  • 效率比普通迭代稍高;
[expression for e in iterator if condision]
lst = list(range(10))
ret = list()

In [9]: %%timeit
   ...: for x in lst:
   ...:     if x % 2 == 0:
   ...:         ret.append(x)
   ...: 
1000000 loops, best of 3: 1.67 µs per loop

In [11]: %%timeit
    ...: [ ret.append(x) for x in lst if x % 2 == 0]
    ...: 
100000 loops, best of 3: 2.33 µs per loop
  • 带多个if

    • 多个if间默认为and关系;

ret = [ x for x in lst if x > 0 if x < 5 if x % 2 == 0]

ret = []
for x in lst:
    if x > 0:
        if x < 5:
            if x % 2 == 0:
                ret.append(x)
  • 多个if语句的,都可以转换为条件的逻辑运算,所以一般来说,不会带多个if语句;
  • 也可以带多个for语句:

[(x,y) for x in range(5) for y in range(5,10)]

相当于逐层嵌套;
ret = []
for x in range(5):
    for y in range(5,10):
        ret.append((x,y))
多个for语句也可跟多个if语句;
[(x,y) for x in range(5) if x > 0 for y in range(5,10) if y < 9]

使用列表解析的目的是为了让代码更简洁。

[x for x in [y for y in range(10)]]

跟着感觉走,如果解析式不能让代码更简洁的情况下,就不要再使用了;

一眼看不出解析式的结果是什么的时候,就不要用了;



问题引入:

    偶数求平方,奇数求立方;

if表达式:

x if cond else y

当条件满足时返回x,当条件不满足时返回y;

使用该表达式与列表解析式结合使用:

[x ** 2 if x % 2 == 0 else x ** 3 for x in lst]

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


ret = 0 

if x % 2 == 0:
    ret = x ** 2
else:
    ret = x ** 3


生成器解析:

列表解析返回的是列表;

range(10000000) 并非马上生成了所有元素;

列表解析是马上生成了所有元素;

(x ** 2 for x in range(10000))

列表解析的中括号变成小括号;

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

g = (x ** 2 for x in range(100000000000))

生成器只有在取值的时候才开始计算;

什么时候用列表解析,什么时候用生成器解析?

需要用下标访问的时候,用列表解析;

只需要对结果迭代的时候,优先使用生成器解析;



集合解析:

{x for x in range(10)}

s = { x for x in range(10)}

操作和列表解析式一样的;



字典解析

{ str(key): v for key in range(10) for v in range(11,20)}

迭代器:

可迭代对象:

r = range(5)

r.__iter__()

可迭代对象,都拥有__iter__()方法;

for x in range(5): pass

for in 语句要求遍历一个可迭代对象;

可迭代对象:

7种数据结构;

range

dict.keys
dict.items
dict.values

迭代器是可迭代对象;

it = iter(range(5))

有__next__方法的可迭代对象叫迭代器;

上述可迭代对象中,没有迭代器;

可迭代对象可以转换为迭代器

    iter()函数可以把一个可迭代对象转换为迭代器;

为什么要转换?

next函数可以从迭代器中取出下一个元素;

迭代器会保存一个指针,指向可迭代对象的当前元素;

调用next函数的时候,会返回当前元素,并且把指针指向下一个元素;

当没有下一个元素时,会抛出StopIteration异常;

for in循环可迭代对象; 首先调用iter方法转换为迭代器,然后不断的调用next方法,知道抛出StopIteration异常

# 迭代器的实现:
it = iter(iteratable):
    while True:
        try:
            next(it)
        except StopIteration:
            return