Python基础笔记:高级特性:切片、迭代、列表生成式、生成器、迭代器

题记:

在python中,代码不是越多越好,而是越少越好。代码不是越复杂越好,而是越简单越好。

1行代码能实现的功能,绝不写5行代码。

请始终牢记:代码越少,开发效率越高。

切片

>>> L=list(range(11)) #生成数0~10
>>> L
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
>>> L[:5] #输出0~4
[0, 1, 2, 3, 4]
>>> L[-5:] #输出倒数第5个~最后
[6, 7, 8, 9, 10]
>>> L[3:7] #输出3~6
[3, 4, 5, 6]
>>> L[0:6:2] #在0~5,每隔2个取一个
[0, 2, 4]
>>> L[::5] #在整个list L上,每隔5个取一个
[0, 5, 10]

 

编写程序:实现一个trim()函数,取出字符串首尾的空格

def trim(x):
    l=len(x)
    a=0
    b=0
    for i in range(l):
        if x[i]!=' ':
            a=i
            break
    if a==l-1:
        return
    else:
        for i in range(l):
            if x[l-i-1]!=' ':
                b=l-i
                break
def trim(x):  #递归函数实现
    if x[0]==' ':
        x=trim(x[1:])
    if x[-1]==' ':
        x=trim(x[:-2])
    return x

>>> from hello import trim
>>> trim('hello      ')
'hello'

迭代(Iterate)

可以迭代的有str,list,tuple,dict ;  迭代是通过for...in来完成的

怎么判断一个对象是否是可迭代对象呢?

>>> from collections import Iterable
>>> isinstance('abc',Iterable)
True
>>> isinstance([1,2,3],Iterable)
True
>>> isinstance(123,Iterable)
False

一些迭代示例:

>>> d={'a':1,'b':2,'c':3} #对dict进行迭代
>>> for key in d: #迭代键值
...     print(key)
...
a
b
c
>>> for v in d.values(): 
...     print(v)
...
1
2
3
>>> for key,v in d.items(): #迭代list里元素
...     print(key,v)
...
a 1
b 2
c 3

for ch in 'ABC': #对str迭代
...     print(ch)
...
A
B
C

>>> for i,value in enumerate(['A','B','C']): #把list变成索引-元素对
...     print(i,value)
...
0 A
1 B
2 C
>>> for i in enumerate(['A','B','C']):
...     print(i)
...
(0, 'A')
(1, 'B')
(2, 'C')
>>> L=[]
>>> for i in enumerate(['A','B','C']): 
...     L.append(i)
...
>>> L
[(0, 'A'), (1, 'B'), (2, 'C')]

编程:使用迭代查找一个list中最小和最大值,并返回一个tuple

def find_mm(x):
    if len(x)==0:
        return (None,None)
    else:
        a=min(x)
        b=max(x)
        return (a,b)

>>> from hello import find_mm
>>> x=[7]
>>> find_mm(x)
(7, 7)

列表生成器

示例:

>>> [x*x for x in range(1,11)] #生成1*1 2*2 ... 10*10 的列表
[1, 4, 9, 16, 25, 36, 49, 64, 81, 100]
>>> [x*x for x in range(1,11) if x%2==0] #仅筛选出偶数的平方
[4, 16, 36, 64, 100]
>>> [m+n for m in 'ABC' for n in 'XYZ'] #生成连个串的全排列
['AX', 'AY', 'AZ', 'BX', 'BY', 'BZ', 'CX', 'CY', 'CZ']
>>> d={'x':'1','y':'2','z':'3'} #把dict生成列表
>>> [k+v for k,v in d.items()]
['x1', 'y2', 'z3']
>>> [k+'='+v for k,v in d.items()]
['x=1', 'y=2', 'z=3']

C:\work>python #在C:\work 目录下打开python解释器
Python 3.6.3 (v3.6.3:2c5fed8, Oct  3 2017, 18:11:49) [MSC v.1900 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> import os #导入os模块
>>> L=[d for d in os.listdir('.')] #os.listdir可以列出文件和目录
>>> ss=[s.upper() for s in L] #把list中所有的字符串变成大写
>>> ss
['HELLO.PY', '__PYCACHE__']
>>> ss=[s.lower() for s in L] #把list中所有的字符串变成小写
>>> ss
['hello.py', '__pycache__']
>>>
>>> for i in ss:
...     if i=='hello.py':
...             print('Right here!')
...
Right here!

内置函数 isinstance(x,str)、isinstance(x,int) 用来判断x是否是str型或int型

>>> x=5
>>> if isinstance(x,int)==True:
...     print('yes!')
...
yes!
>>> x='fuck you!'
>>> if isinstance(x,str)==True:
...     print('yes!')
...
yes!

上面判断一个数据是否可以迭代也是 isinstance() 这个函数(名);

练习:修改列表生成式,通过添加 if 语句保证列表生成式能正确地执行

L1=['Hello','World',18,'Apple',None]

>>> L1 = ['Hello', 'World', 18, 'Apple', None]
>>> L2=[s.lower() for s in L1 if isinstance(s,str)==True]
>>> L2
['hello', 'world', 'apple']

生成器:一边循环一边计算的机制

迭代器:已经计算完毕,进行循环

 

生成器(generator)

要创建一个generator :只要把一个列表生成式的[ ] 改成 ( ) ,就创建了一个generator:

>>> g=(x*x for x in range(10))
>>> g
<generator object <genexpr> at 0x000001E5405C7830>

可以用next() 函数一个一个打印出来generator 的下一个返回值;

>>> g=(x*x for x in range(10))
>>> g
<generator object <genexpr> at 0x000001E5405C7830>
>>> next(g)
0
>>> next(g)
1
>>> next(g)
4
>>> next(g)
9
.....
>>> next(g)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
StopIteration

#genereator 保存的是算法,每次调用next(g),就计算出g的下一个元素的值,直到计算到最后一个元素,没有更多的元素时,抛出StopIteration的错误。

 

当然,generator是可迭代的:

>>> isinstance(g,Iterable)
True
>>> for i in g:
...     print(i)
...
16
25
36
49
64
81
>>>
#generator g 好像有记忆一项,上次利用next函数输出到9,这次从16开始输出!

有输出斐波那契数列的函数:

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

把这个函数换成generator 只需要把 print(b) 改为 yield b 就可以了。

def fib(max):
    n,a,b=0,0,1
    while n<max:
        yield b
        a,b=b,a+b
        n+=1
    return 'done'
a = f() #创建生成器对象

for i in range(10): #斐波那契数列中前10个元素 
    print(a.__next__(), end=' ') 

1 1 2 3 5 8 13 21 34 55

  

>>> from hello import fib
>>> f=fib(5)
>>> for i in f:
...     print(i)
...
1
1
2
3
5
#如果是函数的话:
>>> f=fib(6)
1
1
2
3
5
8

但是用for 循环调用generator 时,发现拿不到generator 的return 语句的返回值。如果想要拿到返回值,必须不过StopIteration 错误,返回值包含在StopIteration 的 value 中:

>>> from hello import fib
>>> g=fib(6)
>>> while True:
...     try:
...             x=next(g)
...             print('g:',x)
...     except StopIteration as e:
...             print('Generator return value:',e.value)
...             break
...
g: 1
g: 1
g: 2
g: 3
g: 5
g: 8
Generator return value: done

编程:输出杨辉三角

def triangle(max):
    n,L=0,[1]
    for i in range(max):
        yield L
        s=[]
        if len(L)>=2:
            for j in range(len(L)-1):
                s.append(L[j]+L[j+1])
        s.append(1)
        s.insert(0,1)
        L=s
    return 'done'
>>> t=triangle(10)
>>> while True:
...     try:
...             x=next(t)
...             print('t:',x)
...     except StopIteration as e:
...             print('Generator return value:',e.value)
...             break
...
t: [1]
t: [1, 1]
t: [1, 2, 1]
t: [1, 3, 3, 1]
t: [1, 4, 6, 4, 1]
t: [1, 5, 10, 10, 5, 1]
t: [1, 6, 15, 20, 15, 6, 1]
t: [1, 7, 21, 35, 35, 21, 7, 1]
t: [1, 8, 28, 56, 70, 56, 28, 8, 1]
t: [1, 9, 36, 84, 126, 126, 84, 36, 9, 1]
Generator return value: done

迭代器

直接作用于 for 循环的数据类型有:

1.集合数据类型,如list、tuple、dict、set、str等;

2.generator ,包括生成器和带yield 的generator function。

可以被next() 函数调用并不断返回下一个值的对象称为迭代器:Iterator

>>> from collections import Iterable 
>>> isinstance([], Iterable) #使用isinstance()#判断一个对象是否是Iterable对象
True
>>> isinstance((x for x in range(10)), Iterator) #判断一个对象是否是Iterator对象
True

你可能会问,为什么listdictstr等数据类型不是Iterator

这是因为Python的Iterator对象表示的是一个数据流,Iterator对象可以被next()函数调用并不断返回下一个数据,直到没有数据时抛出StopIteration错误。可以把这个数据流看做是一个有序序列,但我们却不能提前知道序列的长度,只能不断通过next()函数实现按需计算下一个数据,所以Iterator的计算是惰性的,只有在需要返回下一个数据时它才会计算。

Iterator甚至可以表示一个无限大的数据流,例如全体自然数。而使用list是永远不可能存储全体自然数的。

 

凡是可作用于for循环的对象都是Iterable类型;

凡是可作用于next()函数的对象都是Iterator类型,它们表示一个惰性计算的序列;

集合数据类型如listdictstr等是Iterable但不是Iterator,不过可以通过iter()函数获得一个Iterator对象。

 

posted @ 2018-01-19 17:13  从前有座山,山上  阅读(182)  评论(0编辑  收藏  举报