Python进阶强化训练之对象迭代与反迭代技巧

转载博客地址:https://ansheng.me/

内容源自刘硕老师的《Python进阶强化训练》

视频课程:http://coding.imooc.com/class/62.html


如何实现可迭代对象和迭代器对象?

  • 实际案例

某软件要求从网络抓取各个城市气味信息,并其次显示:

1
2
3
4
北京:  15  20
天津:  17  22
长春:  12  18
......

如果一次抓取所有城市天气再显示,显示第一个城市气温时,有很高的延时,并且浪费存储空间,我们期望以用时访问的策略,并且把所有城市气温封装到一个对象里,可用for语句进行迭代,如何解决?

解决方案

实现一个迭代器对象Weatherlterator,next方法每次返回一个城市气温,实现一个可迭代对象Weatherlterable,————iter__方法返回一个迭代器对象

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
import  requests
 
from  collections  import  Iterable, Iterator
 
 
# 气温迭代器
class  WeatherIterator(Iterator):
     def  __init__( self , cities):
         self .cities  =  cities
         self .index  =  0
 
     def  getWeather( self , city):
         =  requests.get( 'http://wthrcdn.etouch.cn/weather_mini?city='  +  city)
         data  =  r.json()[ 'data' ][ 'forecast' ][ 0 ]
         return  '%s:%s , %s'  %  (city, data[ 'low' ], data[ 'high' ])
 
     def  __next__( self ):
         if  self .index  = =  len ( self .cities):
             raise  StopIteration
         city  =  self .cities[ self .index]
         self .index  + =  1
         return  self .getWeather(city)
 
 
# 可迭代对象
class  WeatherIterable(Iterable):
     def  __init__( self , cities):
         self .cities  =  cities
 
     def  __iter__( self ):
         return  WeatherIterator( self .cities)
 
 
for  in  WeatherIterable([ '北京' '上海' '广州' '深圳' ]):
     print (x)

执行结果如下:

1
2
3
4
5
6
7
C:\Python\Python35\python.exe E: / python - intensive - training / s2.py
北京:低温  21 ℃ , 高温  30
上海:低温  23 ℃ , 高温  26
广州:低温  26 ℃ , 高温  34
深圳:低温  27 ℃ , 高温  33
 
Process finished with exit code  0

如何使用生成器函数实现可迭代对象?

  • 实际案例

实现一个可迭代对象的类,它能迭代出给定范围内所有素数:

1
2
3
4
5
6
7
pn  =  PrimeNumbers( 1 30 )
for  in  pn:
    print (k)
``
输出结果
```text
2  3  5  7  11  13  17  19  23  29

解决方案

-将该类的__iter__方法实现生成器函数,每次yield返回一个素数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
class  PrimeNumbers:
     def  __init__( self , start, stop):
         self .start  =  start
         self .stop  =  stop
 
     def  isPrimeNum( self , k):
         if  k <  2 :
             return  False
         for  in  range ( 2 , k):
             if  %  = =  0 :
                 return  False
 
         return  True
 
     def  __iter__( self ):
         for  in  range ( self .start,  self .stop  +  1 ):
             if  self .isPrimeNum(k):
                 yield  k
 
 
for  in  PrimeNumbers( 1 20 ):
     print (x)

运行结果

1
2
3
4
5
6
7
8
9
10
11
C:\Python\Python35\python.exe E: / python - intensive - training / s3.py
2
3
5
7
11
13
17
19
 
Process finished with exit code  0

如何进行反向迭代以及如何实现反向迭代?

  • 实际案例

实现一个连续浮点数生成器FloatRange(和rrange类似),根据给定范围(start, stop)和步进值(step)产生一些列连续浮点数,如迭代FloatRange(3.0,4.0,0.2)可产生序列:

1
2
正向: 3.0  3.2  3.4  3.6  3.8  4.0
反向: 4.0  3.8  3.6  3.4  3.2  3.0

解决方案

  • 实现反向迭代协议的__reversed__方法,它返回一个反向迭代器

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
class  FloatRange:
     def  __init__( self , start, stop, step = 0.1 ):
         self .start  =  start
         self .stop  =  stop
         self .step  =  step
 
     def  __iter__( self ):
         =  self .start
         while  t < =  self .stop:
             yield  t
             + =  self .step
 
     def  __reversed__( self ):
         =  self .stop
         while  t > =  self .start:
             yield  t
             - =  self .step
 
 
print ( "正相迭代-----" )
for  in  FloatRange( 1.0 4.0 0.5 ):
     print (n)
 
print ( "反迭代-----" )
for  in  reversed (FloatRange( 1.0 4.0 0.5 )):
     print (x)

输出结果

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
C:\Python\Python35\python.exe E: / python - intensive - training / s4.py
正相迭代 - - - - -
1.0
1.5
2.0
2.5
3.0
3.5
4.0
反迭代 - - - - -
4.0
3.5
3.0
2.5
2.0
1.5
1.0
 
Process finished with exit code  0

如何对迭代器做切片操作?

  • 实际案例

有某个文本文件,我们想都去其中某范围的内容,如100~300行之间的内容,python中文本文件是可迭代对象,我们是否可以使用类似列表切片的方式得到一个100~300行文件内容的生成器?

解决方案

  • 使用标准库中的itertools.islice,它能返回一个迭代器对象切片的生成器

1
2
3
4
5
6
7
8
9
10
from  itertools  import  islice
 
=  open ( 'access.log' )
# # 前500行
# islice(f, 500)
# # 100行以后的
# islice(f, 100, None)
 
for  line  in  islice(f, 100 , 300 ):
     print (line)

islice每次训话都会消耗之前的迭代对象

1
2
3
4
5
6
7
=  range ( 20 )
=  iter (l)
for  in  islice(t,  5 10 ):
     print (x)
print ( '第二次迭代' )
for  in  t:
     print (x)

输出结果

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
C:\Python\Python35\python.exe E: / python - intensive - training / s5.py
5
6
7
8
9
第二次迭代
10
11
12
13
14
15
16
17
18
19
 
Process finished with exit code  0

如何在一个for语句中迭代多个可迭代对象?

  • 实际案例

  1. 某班学生期末考试成绩,语文、数学、英语分别存储再3个列表中,同时迭代三个列表,计算每个学生的总分(并行)

  2. 某年纪有四个班,某次考试没班英语成绩分别存储在四个列表中,依次迭代每个列表,统计全学年成绩高于90分人数(串行)

解决方案

  • 并行:使用内置函数zip,它能将多个可迭代对象合并,每次迭代返回一个元组

1
2
3
4
5
6
7
8
9
10
11
12
13
from  random  import  randint
 
# 申城语文成绩,# 40人,分数再60-100之间
chinese  =  [randint( 60 100 for  in  range ( 40 )]
math  =  [randint( 60 100 for  in  range ( 40 )]   # 数学
english  =  [randint( 60 100 for  in  range ( 40 )]   # 英语
 
total  =  []
 
for  c, m, e  in  zip (chinese, math, english):
     total.append(c  +  +  e)
 
print (total)

执行结果如下:

1
2
3
4
C:\Python\Python35\python.exe E: / python - intensive - training / s6.py
[ 232 234 259 248 241 236 245 253 275 238 240 239 283 256 232 224 201 255 206 239 254 216 287 268 235 223 289 221 266 222 231 240 226 235 255 232 235 250 241 225 ]
 
Process finished with exit code  0

  • 串行:使用标准库中的itertools.chain,它能将多个可迭代对象连接

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
from  random  import  randint
from  itertools  import  chain
 
# 生成四个班的随机成绩
e1  =  [randint( 60 100 for  in  range ( 40 )]
e2  =  [randint( 60 100 for  in  range ( 42 )]
e3  =  [randint( 60 100 for  in  range ( 45 )]
e4  =  [randint( 60 100 for  in  range ( 50 )]
 
# 默认人数=1
count  =  0
 
for  in  chain(e1, e2, e3, e4):
     # 如果当前分数大于90,就让count+1
     if  s >  90 :
         count  + =  1
         
print (count)

输出结果

1
2
3
4
C:\Python\Python35\python.exe E: / python - intensive - training / s6.py
48
 
Process finished with exit code  0

转载博客地址:https://ansheng.me/

内容源自刘硕老师的《Python进阶强化训练》

视频课程:http://coding.imooc.com/class/62.html


  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值