1. 程式人生 > 程式設計 >Python高效程式設計技巧筆記(三)物件迭代與反迭代相關問題與解決技巧

Python高效程式設計技巧筆記(三)物件迭代與反迭代相關問題與解決技巧

如何實現可迭代物件和迭代器物件

實際案列

某網路要求抓取各個城市氣溫資訊,並依次顯示:

北京:15~20

天津:17~22

長春:12~18

...

如果一次抓取所有城市氣溫在顯示,顯示第一個城市氣溫時,有很高的延時,並且浪費儲存空間,我們期望以""用時訪問"策略,並且把所有城市氣溫封裝到一個物件裡,可以用for語句迭代,如何解決?

from collections import Iterable Iterator
l=[1,2,3,4,5]
for i in l:
print(i)
isintances(l,Iterable)
true
issubclass(list,Iterable)
iter(l)
#迭代器物件是由可迭代物件生成的,iter其實是實現了l.__iter__方法
#next對迭代器進行迭代,沒迭代一次就出現一個元素 iter(l)~---it=====(next) iter~~it~~.(StopIteration it=iter(l) it__iter__ 複製程式碼

如何使用生成器函式實現可迭代物件?

實際案例

實現一個可迭代物件的類,他能迭代出給定範圍內所有素數:

pn=PrimeNumbers(1,30)
for k in pn:
    print k,輸出結果:
2,5,7,11,13,17,19,23,29
複製程式碼

解決方案:

將該類的__iter__方法實現生成器函式,每次yield返回一個素數

from collections import
Iterable Iterabor import requests class WeatherIterator(Iterator): def__init__(self,caties): self.caties=caties self.index=0 def __next__(self): if self.index == len(self.caties): raise StopIteration city = self.cities[self.iindex] self.index+=1
reurn self.get_weather(city) def get_waather(self,city): url='http://wthrcdn,etouch.cn/weather_mini?city=='+city r=requests.get(url) data=r.json()['data']['forecast'][0] return city,data['high'],data['low'] class WeatherIterable(Iterable): def __init__(self,cities): self.cities=cities def __iter__(self): return WeatherIterator(self.cities): def show(w): for x in w: print(x) 複製程式碼

生成器函式就是包含了yield語句的函式

def f():
    yield('in f 1')
    yield1
    yield('in f 2')
    yield2
    yield('in f 3')
    yield3
    
f()
(g,Iterator)
(g,Iterable)

class XXX_iTERABLE(Iterable):
    def__def__iter__():
class PrimeNumbers(Iterable):
    def __init__(self):
        pass
    def __iter__(self):
        for k in range(self.a,self.b+1)
            if self.is_prime(K):
                yield k
                
    def is_prime(self,k)
        #if k <2:
        #   return False
        
        #[2,k-1]
        #for x in range (2,k)
        #    if k % x ==0:
        #        return False
        return False if x<2 else all(map(lambda x:k % x,range(2,k)))
        return True
        
pn = PrimeNumbers(1,30)
for n in pn:
    print(n)
複製程式碼

如何進行反向迭代以及如何實現反向迭代?

研討問題:

如何進行反向迭代以及如何進行反向迭代?

實際案例:

實現一個連續浮點數發生器FloatRange(和range類似)根據給定範圍(start,end)和步進值(step)產生一些列連續浮點數,如迭代FloatRange(3.0,4.0,0.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__方法,它返回一個反向迭代器。

from decimal import Decimal
class FloatRange():
def __init__(self,a,b,step):
    self.a=Decimal(str(a))
    self.b=Decimal(str(b))
    self.step=Decimal(str(step))
    
def __iter__(self):
    t=self.a
    while t<=self.b
        yield float(t)
        t+=self.step
def __reversed__(self):
    t=self.b
    while t>=self.a:
        yield float(t)
        t-=self.step
fr = FloatRange(3.0 4.0,0.2)
for x in fr:
    print(x)
print('-'*20)
for x in reversed(fr):
    print(x)
複製程式碼
from decimal import Decimal
Decimal('0.2')
from functools import reduce
reduce(Decimal.__add__,[Decimal('0.2')]*5)
複製程式碼

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

實際案例:

有某個文字檔案,我們想讀取其中某個範圍的內容如100~300行之間的內容,python中檔案是可迭代物件,我們是否可以使用列表切片的方式得到一個100~300行檔案內容的生成器?

f=open('/var/log/dpkg')
for line in f[100:300]:  #可以嗎?
...
複製程式碼

解決方案:

使用itertools.islice,它能返回一個迭代物件切片的生成器.

f=open('/var//log/dpkg.log.1')
f.__
for line in islice(f,100~1,300)
    print(x)
def my_ilice(iterable,startend,step=1)
    for i,x in enumerate(Iterable,seep=1)
    tmp=0
    for i in enumerate(iterable):
        if i>=end:
            break
        if i>=start:
            if tmp==0
                tmp=step
                yield x
            tmp-=1
print(list(my_islice(range(100,150),10,20,3)))
from itertools import islice
print(list(islice(range(100,3)))
複製程式碼

如何在一個for語句中迭代多個可迭代物件?

研討問題:

如何在一個for語句中迭代多個可迭代物件

實際案例:

1.(並行)某班學生考試成績,語文,數學,英語分別儲存在3個列表中,同時迭代三個列表,計算每個學生的總分.

2.(序列)某年級有4個班,某次考試每班英語成績分別儲存在4個列表中,依次迭代每個列表,統計全年成績高於90分人數.

解決方案:

1.並行:使用內建函式zip,它能將多個可迭代物件合併,每次迭代返回一個元組.

from random import randint
chinese = [randint(60.100) for _ in range(20)]
math = [randint(60,100) for _ in range(20)]
english = [randint(60,100) for _ in range(20)]
t=[]
for s1,s2,s3 in zip(chinese,math,english)
    t.append(s1+s2+s3)
    
[sum(s) for s in zip(chinese,english)]
list(map()sum,zip(chinese,english))
list(map(lambda s1,s3:s1+s2+s3,chinese,english))
map(lambda *args:args,english)
map(zip(chinese,english))
list(map(None,english))
複製程式碼

2.序列:使用標準庫中的itertools.chain,它能將多個迭代物件連線.

from itertools import chain
for x in chain([1,2,3],[4,5,6,7],[8,9]):
    print(x)
    
s='abc;123|xyz;678|fweuow \  t7zka'
list(map(lambda ss:ss.split('|'),s.split(';')))
(list(chain[*[list(map(lambda ss:ss.split('|'),s.split(';')))]])

from functools import reduce 
list(reduce(lambda it_s,sep:chain(*map(lambda ss:ss.split(sep),it_s)),';|\t',[s]))
複製程式碼

總結:主要講解迭代器和迭代器物件,反向迭代。迭代器切片以及生成器函式實現可迭代物件.