初學 python的 with 和 yield

不久前面試時候面試官提起了python的這兩個關鍵字,問我瞭解過沒有,我當時沒能答上來,接觸python時間太短,雖然只是隨口一問,我還是隨後查資料。

yield

找到了一篇關於yield的神文:(譯)Python關鍵字yield的解釋(stackoverflow)
這篇文章翻譯自 stackoverflow 上一篇帖子,介紹的非常詳細了,yield返回的就是生成器,“生成器是可以迭代的,但是你 只可以讀取它一次 ,因爲它並不把所有的值放在內存中,它是實時地生成數據。”
我寫的是我讀後總結,所以有不夠詳盡的地方,建議直接閱讀上面的文章。
for … in … 是一個迭代器,他可以遍歷迭代的內容。

index = (x+x for x in range(3)) # 這是一個生成器
for i in range(index):
	print(i)
	
for i in range(index): # 執行程序,你會發現,第二次根本沒有打印出數據
	print(i)

輸出內容:可以看到只有一次輸出

0
2
4

yield 生成器舉例:

class test()
	def testYield()
		for i in range(3):
			yield i

t = test()
index = t.testYield()
for i in index:
	print(i)
	
index = t.testYield()
for i in index:
	print(i)

輸出內容:可以看到,重新調用生成器方法後,就可以再進行讀取了。

0
1
2
0
1
2

我因爲沒有python的項目經驗,所以對yield的具體理解只能到此爲止。

with

之前編寫批量修改文件的時候有用到過,記憶不深,在這裏再強化一下。
with經常適用於try except finally 的優化,當然,with適用的範圍不止是try catch。

fileName = "server.log"
# 讀取文件
f = open(fileName, 'r')
try:
	e = f.read()
except:
	pass
finally:
	f.close()

# 上面代碼等同於
with open(fileName) as f:
	f.read()

用with更加簡潔美觀,而且就算髮生異常,也會執行完畢f.close()。

with的原理是,with後代碼返回的對象需包含 __enter__() 和 __exit__() 的方法,先執行 __enter__() ,然後執行代碼塊,將返回值賦給 as 後面的變量在內容中使用,然後執行內容,結束或者發生異常會先調用代碼塊的 __exit__() 。結合這個,可以設計出適用with的代碼結構。

class test():
    def __enter__(self):
        print("1.enter")
        return self
    def __exit__(self, etype, evalue, etraceback):
        print("type is %s" % etype)
        print("type is %s" % evalue)
        print("type is %s" % etraceback)
        print("3.exit")
    def t(self):
        x = 1/0
        print("2.test" + x)

with test() as t:
	t.t()

輸出:可見,在異常被捕捉前,__exit__()執行完畢。

1.enter
type is <type 'exceptions.ZeroDivisionError'>
type is integer division or modulo by zero
type is <traceback object at 0x10314aea8>
3.exit
Traceback (most recent call last):
  File "test.py", line 17, in <module>
    t.t()
  File "test.py", line 13, in t
    x = 1/0
ZeroDivisionError: integer division or modulo by zero
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章