不久前面試時候面試官提起了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