python高级特性的一般认识
列表生成
[x * x for x in range(1, 11)]
写列表生成式时,把要生成的元素x * x放到前面,后面跟for循环,或者跟其他的表达式。
例如,题目是要你把偶数全部筛选出来:
a=[x for x in range(1,11) if x%2==0] print(a) #[2, 4, 6, 8, 10]
python的哲学应该是代码写得越少越好,这样开发效率高。
迭代器
第一,像字符str,列表list,元组turple,字典dict等等都是可迭代对象iterable,内置有__iter__方法的对象,即obj.__iter__,如下
‘hello‘.__iter__
(1,2,3).__iter__
[1,2,3].__iter__
{‘a‘:1}.__iter__
{‘a‘,‘b‘}.__iter__
open(‘a.txt‘).__iter__但是像这一类没有obj.__next__()方法。不能用next()方法去迭代。
第二,像generator生成器都是迭代器对象iterator,也就是说内置有__iter__方法以及__next__方法。
文件类型是迭代器对象 open(‘a.txt‘).__iter__() open(‘a.txt‘).__next__()
也就是说,生成器都是Iterator对象,但list、dict、str虽然是Iterable,却不是Iterator。可以用iter()函数让他们变成迭代器对象。
你可能会问,为什么list、dict、str等数据类型不是Iterator?
这是因为Python的Iterator对象表示的是一个数据流,Iterator对象可以被next()函数调用并不断返回下一个数据,直到没有数据时抛出StopIteration错误。可以把这个数据流看做是一个有序序列,但我们却不能提前知道序列的长度,只能不断通过next()函数实现按需计算下一个数据,所以Iterator的计算是惰性的,只有在需要返回下一个数据时它才会计算。
Iterator甚至可以表示一个无限大的数据流,例如全体自然数。而使用list是永远不可能存储全体自然数的。
生成器
1.第一种方法
要创建一个generator,有很多种方法。第一种方法很简单,只要把一个列表生成式的[]改成(),就创建了一个generator:
>>> L = [x * x for x in range(10)] >>> L [0, 1, 4, 9, 16, 25, 36, 49, 64, 81] >>> g = (x * x for x in range(10)) >>> g <generator object <genexpr> at 0x1022ef630>
创建L和g的区别仅在于最外层的[]和(),L是一个list,而g是一个generator。
我们使用next()或者.__next__()方法可以获得genereaor的下一个返回值:
>>> g = (x * x for x in range(10)) >>> next(g) 0 >>> next(g) 1 >>> next(g) 4 >>> next(g) 9 >>> next(g) 16 >>> next(g) 25 >>> next(g) 36 >>> next(g) 49 >>> next(g) 64 >>> next(g) 81 >>> next(g) Traceback (most recent call last): File "<stdin>", line 1, in <module> StopIteration >>>
next()方法可以卡点。运行一次到下一个位置,然后再卡点,没有更多的元素时,抛出StopIteration的错误。但是一直用next()属实sb,数据集太大怎么循环,所以用for,因为generator也是可迭代对象。
a=(x for x in range(1,11) if x%2==0)
for i in a:
print(i)
2
4
6
8
102.第二种方法
def odd():
print(‘step 1‘)
yield 1
print(‘step 2‘)
yield(3)
print(‘step 3‘)
yield(5)
a=odd()
res=next(a)
print(a)
print(res)
step 1
<generator object odd at 0x0000025945C37660>
1下面实现用yield和for循环对函数进行循环,准确来讲是迭代器函数(我自己起的名字)
def odd():
print(‘step 1‘)
yield 1
print(‘step 2‘)
yield(3)
print(‘step 3‘)
yield(5)
# res=next(a)
# print(a)
# print(res)
for i in odd():
print(i)step 1 1 step 2 3 step 3 5
牛逼了,用yield将函数转化成生成器,让他可迭代,我查验了一下,odd()具备了iter和next方法,yield让函数有了"卡点"的功能。
for循环
#基于for循环,我们可以完全不再依赖索引去取值了
dic={‘a‘:1,‘b‘:2,‘c‘:3}
for k in dic:
print(dic[k])
#for循环的工作原理
#1:执行in后对象的dic.__iter__()方法,得到一个迭代器对象iter_dic
#2: 执行next(iter_dic),将得到的值赋值给k,然后执行循环体代码
#3: 重复过程2,直到捕捉到异常StopIteration,结束循环就此我们知道了for的真正原理。还有可next()必是迭代器和生成器,它们表示一个惰性计算的序列;可iter()不一定是生成器迭代器,可能是可迭代对象iterable。
所以python里面的for是惰性计算,按理来说可以计算到无穷大的数。