生成器:是自定義的迭代器(本身用python代碼寫的迭代器),函數中見到yield的就是生成器python
那麼yield先後的變量又該怎麼理解面試
看例子一app
def counter(name): print('%s ready to count'%name) num_list=[] while True: #這個語句的做用是循環利用yield,這樣的話對象就能夠無限傳值了 #yield前的變量是接收值的
num=yield '如今的列表是%s'%num_list #yield後面的變量會打印處理
num_list.append(num) print('%s start to count %s'%(name,num)) e=counter('xincheng') print(e.send(None)) #或者 next(e)
print(e.send('1')) print(e.send('2')) for i in range(3,10): print(e.send(i))
例子一打印結果爲:ide
xincheng ready to count 如今的列表是[] xincheng start to count 1 如今的列表是['1'] xincheng start to count 2 如今的列表是['1', '2'] xincheng start to count 3 如今的列表是['1', '2', 3] xincheng start to count 4 如今的列表是['1', '2', 3, 4] xincheng start to count 5 如今的列表是['1', '2', 3, 4, 5] xincheng start to count 6 如今的列表是['1', '2', 3, 4, 5, 6] xincheng start to count 7 如今的列表是['1', '2', 3, 4, 5, 6, 7] xincheng start to count 8 如今的列表是['1', '2', 3, 4, 5, 6, 7, 8] xincheng start to count 9 如今的列表是['1', '2', 3, 4, 5, 6, 7, 8, 9]
例子二:函數
def counter(name): print('%s ready to count'%name) num_list=[] while True: num=yield num_list,'hehe' #yield後面的變量會答應處理,多個用,隔開,結果就會放入一個元組中
num_list.append(num) print('%s start to count %s'%(name,num)) #yield後面的語句通常爲下一個yield的開始
e=counter('xincheng') next(e) s=e.send('1') #xincheng start to count 1
print(s,type(s)) #(['1'], 'hehe') <class 'tuple'> yield後面的東西是給對象傳的值,多個值放在一個元組中
例子三:yield from 能夠從一些地方獲取值spa
def gen1(): for c in 'ab': yield c for i in range(3): yield i print(list(gen1())) def gen2(): yield from 'ab'
yield from range(3) print(list(gen2())) #兩個print的值都爲['a', 'b', 0, 1, 2]
面試題一code
def demo(): for i in range(4): yield i g=demo() g1=(i for i in g) g2=(i for i in g1) print(list(g1)) #[0, 1, 2, 3]
print(list(g2)) #[]
#g是第一個生成器,g1取得值來自於g,g2取值來自於g1,歸根到底仍是g,list是可迭代對象,將g1賦予list得方法,實際上是從g中取值,並且取完了,g2天然就是空值了
請看下面得變體
def demo():
for i in range(4):
yield i
g=demo()
g1=(i for i in g)
g2=(i for i in g1)
print(next(g)) # 0
print(next(g1)) # 1
print(next(g2)) # 2
面試題二:對象
def add(n,i): return n+i def test(): for i in range(4): yield i g=test() for n in [1,10]: g=(add(n,i) for i in g) print(list(g)) #此例子的for循環中有兩個元素,其結果爲 [20, 21, 22, 23]
#若是將for循環下面得表達式換成g=[add(n,i) for i in g] 換成了【】,結果爲[11, 12, 13, 14]
#若是將for循環的表達式換成 for n in [1,3,10] 或者 for n in [1,11,10] 都是三個元素,其結果爲[30, 31, 32, 33]
#若是是 for n in [1,3,6,7,10,11,100,10]總共8個元素 其結果爲[80, 81, 82, 83]
面試二總結:生成器的特色是惰性機制,也就是說你找它要,它纔會給你值blog
在上一題的for循環中,無論你循環多少次,生成器的取值都是列表【】中的最後一個值內存
g在取值前,是一個內存地址,for循環一直改變着g的內存地址,最後是n=10的內存地址
for循環一次,g中的值就加一次,每次加的都是n=10的內存地址的值
for循環第一次: 10+0 10+1 10+2 10+3
for循環第二次:10+10+0 10+10+1 10+10+2 10+10+3
若是有第三次:10*3+0 10*3+1 10*3+2 10*3+3
。。。。。。