美文网首页
Python高级特性-2

Python高级特性-2

作者: MrTrying | 来源:发表于2018-07-23 22:34 被阅读20次

列表生成式

#生成[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
#直接创建
arr = list(range(0, 10))
print(arr)

#列表生成式
arr = [x for x in range(0, 10)]
print(arr)

上面两段代码效果相同,都是生成0~9的list,第二段代码使用的是列表生成式。

其中第二个x表示for..in迭代的元素,第一个x表示添加到list中的元素;第一个x还可以替换成其他的,例如表达式

arr = [0 for x in range(0, 10)]
print(arr)
#输出:[0, 0, 0, 0, 0, 0, 0, 0, 0, 0]

arr = [x*2 for x in range(0, 10)]
print(arr)
#输出:[0, 2, 4, 6, 8, 10, 12, 14, 16, 18]

for..in后面还能加上if条件判断。抱着怀疑的态度,试了试在直接使用for..in进行迭代的情况下添加if判断,结果报错了。

arr = [x * x for x in range(0, 10) if x % 2 == 0]
print(arr)
#输出:[0, 4, 16, 36, 64]

还有一个比较强大的地方,列表生成式支持for..in的叠加,也就是循环的嵌套

arr = [m + n for m in '123'for n in 'abc']
print(arr)
#输出:['1a', '1b', '1c', '2a', '2b', '2c', '3a', '3b', '3c']

for..in所支持的迭代类型,在列表生成式中都是可以使用的,例如字符串,dirt,dirt.values(),dirt.items()等,都是可以使用的。而在列表生成式的第一个x的位置,出了表达式,还支持第二个x类型所支持的函数。

生成器(generator)

列表生成式是一次直接创建了一个完整的list,而生成器则不必创建一个完整的list,可以一边循环一边创建list中的元素,这样跟更加节省内存。

#生成式中的[]变成()
g = (x for x in range(10))

这样就创建了一个generator,并不是list,可以通过next(g)函数获取生成的元素,next会获取下一个生成的元素。而generator也是支持迭代的,这样才更加合理,不需要无限的调用next(g),并且不需要关心StopIteration的错误。当next(g)不能生成元素了会报StopIteration错误。

g = (x for x in range(10))
for n in g:
    print(n)

在较复杂的情况下,无法用迭代完成时,generator可以用函数来实现。比如,著名的斐波拉契数列(Fibonacci),除第一个和第二个数外,任意一个数都可由前两个数相加得到:

1, 1, 2, 3, 5, 8, 13, 21, 34, ...

斐波拉契数列用列表生成式写不出来,但是,用函数把它打印出来却很容易:

def fib(max):
    n, a, b = 0, 0, 1
    while n < max:
        print(b)
        a, b = b, a + b
        n = n + 1
    return 'done'

上面的函数打印了斐波那契数列的前max个数,这里只需要把print(b)修改成yield(b)fib函数就变成了一个generator

def fib(max):
    n, a, b = 0, 0, 1
    while n < max:
        yield(b)
        a, b = b, a + b
        n = n + 1
    return 'done'

直接打印fib(4)时,已经不是按照之前的规则输出数列,结束时输出done,而是这样一串字符

<generator object fib at 0x000001E7F04B8258>

这是因为generator和函数的执行流程不同,函数是顺序执行遇到return或者执行完成就结束了;而generator则是在每次条用next时执行,遇到yield语句返回,再次执行next时从上次的yield继续执行。举个例子:

def odd():
    print('step 1')
    yield (1)
    print('step 2')
    yield (2)
    print('step 3')
    yield (3)


o = odd()
print(next(o))
print(next(o))
print(next(o))

输出结果:

step 1
1
step 2
2
step 3
3 

从输出结果可以看得出来,每调用一次next都会停在yield的地方,下一次执行next有会接着从这里开始。执行3次yield后,已经没有yield可以执行了,所以,第4次调用next(o)就报错。

同时这里还会发现一个问题,当使用yield将函数变成generator函数是无法获取return的值。如果想要拿到返回值,必须捕获StopIteration错误,返回值包含在StopIterationvalue中。

迭代器

之前提高过迭代的概念,也就是for..in,支持的数据类型有listtupledictsetstr等;generatorgenerator函数也是支持的,这些都是Iterable对象。在迭代中有提到isinstance()函数可以判断一个对象是否是Iterable对象。

其中generator不仅可以使用for循环并且可以使用next()函数并不断返回下一个值,这样的对象被称为迭代器(Iterator)

同样可以使用isinstance()函数判断一个对象是否是Iterator对象

from collections import Iterator

print(isinstance([], Iterator))
print(isinstance({}, Iterator))
print(isinstance('', Iterator))

以上上种类型输出的结果都是False

这里有一点需要注意,generatorIterator,但listdictstr虽然是Iterable,却不是Iterator。使用iter()函数可以将listdictstrIterable变成Iterator

for循环的本质就是通过不断条用next()函数实现的。

相关文章

  • Python高级特性-2

    列表生成式 上面两段代码效果相同,都是生成0~9的list,第二段代码使用的是列表生成式。 其中第二个x表示for...

  • python高级特性(2)

    一、生成器 通过列表生成式,我们可以直接创建一个列表。但是收到内存限制,列表容量肯定是有限的。而且,创建一个包含1...

  • 学习笔记系列——基础知识(三)

    人生苦短,我用python 高级特性: 切片(slice): list[0:n] list[-2:]--倒数切...

  • Python学习(三)

    Python的高级特性 python中有很多高级特性,比起C/C++来说要简单许多,运用起来十分方便。 切片 通常...

  • Python高级特性

    切片slice取指定索引范围的操作:[0:10:2]-->意为从第一个元素到第11个元素,元素之间隔2 迭代ite...

  • python 高级特性

    1.切片对取数据很方便,如取一个list的前n个元素,没有接触到切片的,可以使用循环,但是用切片就会很简单: 也支...

  • Python高级特性

    切片 迭代 列表生成式 生成器 generator generator:按照某种算法推算出来结果,是一种一边循环一...

  • Python——高级特性

    #!/usr/bin/python # -*- coding:UTF-8 -*- __author__ = 'wx...

  • python高级特性

    python高级特性 iteration迭代 对list,tuple的遍历被称为迭代。对list实现类似Java那...

  • python高级特性

    一、列表生成器 1. 形式: [表达式 for ... in 可迭代类型 [if expression] ] 2....

网友评论

      本文标题:Python高级特性-2

      本文链接:https://www.haomeiwen.com/subject/nwjsmftx.html