第七篇:三元表達式、推導式、生成器、迭代器

三元表達式

num = float(input('請輸入一個數字:'))
result = '偶數' if num%2 == 0 else '奇數'
print(result)

'''相似於'''
if num%2 == 0:
    print('偶數')
else:
    print('奇數')

推導式

推導式是python提供的另外一種建立數據類型的方式,有列表推導式、集合推導式、字典推導式,沒有元祖推導式。python

列表推導式

x = [1,2,3,4,5]
y = [6,7,8,9,10]
transfrom = [1 if i%2==0 else 0 for i in x if i > 2]
print(transfrom)
'''相似於'''
transfroms = []
for i in x:
        if i > 2:
            if i%2==0:
                transfroms.append(1)
            else:
                transfroms.append(0)
print(transfroms)


result = [i+e for i in x if i%2==0 for e in y if e%2 == 0]
print(result)
print(type(result))
'''相似於'''
results = []
for i in x:
    for e in y:
        if i%2==0:
            if e%2==0:
                results.append(i + e)
print(results)


'''1,2,3,4組成無重複三位數'''
a = [str(i) for i in range(1,5)]
f = [b+c+d for b in a for c in a for d in a if b != c != d != b]
print(f)

集合推導式

'''1,2,3,4組成無重複三位數'''
a = [str(i) for i in range(1,5)]
f = {b+c+d for b in a for c in a for d in a if b != c != d != b} #把[]改成{}便可。
print(len(f))

字典推導式

x = [1,2,3,4,5]
y = [6,7,8,9,10]
result = {i:e for i,e in zip(x,y)} #zip函數返回zip對象,被遍歷時返回一個序列下標相同的元素組成的元祖
res = {i:e for i,e in enumerate(y)} #enumerate()函數返回enumerate對象,被遍歷時返回一個元祖(下標,元素)。
print(result)
print(type(result))
'''相似於'''
results = {}
for i,e in enumerate(y):
    results[i] = e
print(results)
print(zip(x,y).__next__())

生成器

在Python中,列表,字典等序列的全部數據都在內存裏,若是有海量數據,而咱們僅僅須要訪問幾個元素的時候,那絕大多數元素佔用的空間都白白浪費了。那麼,有沒有既想要獲得龐大的數據,又想讓它佔用空間少的方法呢?,那就用生成器!按照某種算法不斷推算出後續的元素,須要訪問某個元素的時候,只需推算出,而不是從龐大的數據序列裏取出算法

。這樣一邊循環一邊計算的機制,稱爲生成器:generator。若要訪問generate對象的元素,須要調用它的__next__()函數,或把generate對象傳入next()函數,一個__next__()函數只拿出一個,以後循環中止在當前位置,下一個再取值再從中止位置繼續向前取值。若推算完全部元素,還調用__next__(),則會拋出StopIteration異常,next()函數也同樣。app

建立生成器

'''方式一(生成器表達式):只要把一個列表推導式式的[]改爲(),就建立了一個generator對象。'''
generate = (e for e in range(1,100,2))
print(type(generate))

#訪問元素
print(generate.__next__())
print(generate.__next__())
print(next(generate))  #在同一個對象裏,不管調用next()或__next__()函數,它們都是接力推算的。
print(generate.__next__())
print(next(generate))
print("*"*10,end='\n'*2)

generate2 = (e for e in range(1,10,2)) #從新建立新對象
for e in generate2: #for循環會不斷調用__next__函數推算出後續元素,並返回它,直到捕獲StopIteration異常,而後自動結束for循環。
    print(e)


'''方式二:若是一個函數中包含yield關鍵字,那麼這個函數就再也不是一個普通函數,而是一個generator。
調用函數就是建立了一個生成器(generator)對象。yield至關於 return 返回一個值,而且記住這個返回的位置,
下次迭代時,代碼從yield的下一條語句開始執行。'''
def test(seq):
    index = 0
    while index < len(seq):
        yield seq[index] #遇到yield時,返回一個值,執行中止,並記住該位置,下次調用__next__()時,代碼從yield的下一條語句開始執行。。
        print('*'*10)
        print('上一個元素的下標是{}'.format(index))
        index += 1
str1 = 'abcdefgh'
generate3 = test(str1)
print(type(generate3))
print(generate3.__next__())
print(generate3.__next__())

#.send() 和next()同樣,都能讓生成器繼續往下走一步(下次遇到yield停),但send()能傳一個值,這個值做爲yield表達式總體的結果.
def test1():
    count = 1
    while count < 9:
        it = yield count
        print('*'*10)
        count += 1
        if it:
            print('你第{}次使用的是:send()函數傳值,並賦值給了變量step,step = {}'.format(count,it))
        else:
            print('你第{}次使用的是:__next__()函數,未給變量step傳值,默認值爲None,step = None'.format(count))
generate4 = test1()
print('返回值爲:{}'.format(generate4.send(None))) #不能使用send()函數向剛啓動的生成器發送非空值,否則使用__next__(),不然報錯。
print('返回值爲:{}'.format(generate4.send(6)))
print('返回值爲:{}'.format(generate4.send(8)))
print('返回值爲:{}'.format(generate4.__next__()))
print('返回值爲:{}'.format(generate4.send(9)))
print('返回值爲:{}'.format(generate4.__next__()))
def permutations(iterable, r=None):
    # permutations('ABCD', 2) --> AB AC AD BA BC BD CA CB CD DA DB DC
    # permutations(range(3)) --> 012 021 102 120 201 210
    pool = tuple(iterable)
    n = len(pool)
    r = n if r is None else r
    if r > n:
        return
    indices = list(range(n))
    cycles = list(range(n, n-r, -1))
    yield tuple(pool[i] for i in indices[:r])
    while n:
        for i in reversed(range(r)):
            cycles[i] -= 1
            if cycles[i] == 0:
                indices[i:] = indices[i+1:] + indices[i:i+1]
                cycles[i] = n - i
            else:
                j = cycles[i]
                indices[i], indices[-j] = indices[-j], indices[i]
                yield tuple(pool[i] for i in indices[:r])
                break
        else:
            return
View Code

迭代器

Iterable(可迭代對象): 有迭代能力的對象,一個類,實現了__iter__(),那麼就認爲它有迭代能力,一般此函數返回一個實現了__next__()的對象(雖然這個要求不強制),若是本身實現了,你能夠返回self,固然這個返回值不是必須的。ide

Iterator(迭代器): 迭代器(固然也是Iterable),同時實現了__iter__()__next__()的對象,缺乏任何一個都不算是Iterator,其中__next__()應該在迭代完成後,拋出一個StopIteration異常。函數

可使用  collections.abc 裏面的 Iterator 和  Iterable 配合  isinstance 函數來判斷一個對象是不是可迭代的,是不是迭代器對象。spa

咱們在使用for語句的時候,python內部實際上是把for後面的對象上使用了內建函數iter(),返回一個迭代器對象(Iterator),它主要映射到了類裏面的__iter__()函數,此函數返回的是一個實現了__next__的對象。for語句會自動處理這個StopIteration異常以便結束for循環。code

from collections.abc import *
list1 = [1,2,3,4,5]
str1 = 'abcdef'
list2iterator = iter(list1) #接受可迭代對象,返回迭代器對象。
str2iterator = iter(str1)

'''isinstance() 函數來判斷一個對象是不是一個已知的類型,相似 type()。type() 不會認爲子類是一種父類類型,不考慮繼承關係。
isinstance() 會認爲子類是一種父類類型,考慮繼承關係。'''
print('list1是可迭代對象嗎?:{} | list1是迭代器對象嗎?:{}'.format(isinstance(list1,Iterable),isinstance(list1,Iterator)))
print('str1是可迭代對象嗎?:{} | str1是迭代器對象嗎?:{}'.format(isinstance(str1,Iterable),isinstance(str1,Iterator)))
print('list2iterator是可迭代對象嗎?:{} | list2iterator是迭代器對象嗎?:{}'.format(isinstance(list2iterator,Iterable),isinstance(list2iterator,Iterator)))
print('str2iterator是可迭代對象嗎?:{} | str2iterator是迭代器對象嗎?:{}'.format(isinstance(str2iterator,Iterable),isinstance(str2iterator,Iterator)))


class B(object):
    def __next__(self):
        raise StopIteration

class A(object):
   def __iter__(self):
       return B()

a = A()
b = B()
print(isinstance(a, Iterable))
print(isinstance(a, Iterator))
print(isinstance(b, Iterable))
print(isinstance(b, Iterator))


'''製做本身的迭代器'''
class MyIterator():
    def __init__(self,seq):
        self.index = 0
        self.seq = seq
    def __iter__(self):
        return self
    def __next__(self):
        if isinstance(self.seq,dict):
            self.seq = list(self.seq.values())
            res = self.seq[self.index]
            self.index += 1
            return res
        else:
            if self.index < len(self.seq):
                element = self.seq[self.index]
                self.index += 1
                return element
            else:
                raise StopIteration()  #在不想繼續有迭代的狀況下拋出一個StopIteration的異常,由for語句會捕獲這個異常,而且自動結束for。

test = 'abcdef'
testIter = MyIterator(test)
print(isinstance(testIter,Iterable))
print(isinstance(MyIterator,Iterable)) #__iter__()和__next__()是類的普通方法,不是類方法或靜態方法,只能被實例化對象調用,因此不能經過類名判斷它是不是迭代器。
print(isinstance(MyIterator(test),Iterator))
相關文章
相關標籤/搜索