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