python中with的作用_python中with的用法

一、文件操作

#自行车

f=open("filename")

f.write()

f.close()

上述代码存在的问题:

(1)直接open()打开需要手动关闭,并且容易忘记关闭

(2)当文件操作出现异常导致程序提早离开,而没有执行关闭文件操作

#小轿车

try:

f=open("xxx")

f.write()#文件操作

except:

do somethingfinally:

f.close()

虽然功能完善了,但是代码这么冗余,也太笨了吧

#特斯拉

with open("xxx") as f:

f.write()#文件操作

一个with代码块直接解决一切,无论怎样的方式退出代码块都会自动关闭文件

问题来了,

with为什么可以做到自动关闭文件?

with为什么即便文件操作中出现异常也可以正常关闭文件?with语句和原始open同样返回一对象,有什么不一样?

二、with原理

__enter__()方法:紧跟with后面的语句被求值后,返回对象的__enter__()方法被调用,这个方法的返回值将被赋值给as后面的变量。

__exit__()方法:当with后面的代码块全部被执行完之后,将调用前面返回对象的__exit__()方法

classTest(object):def __enter__(self):print("执行了 __enter__方法")return "enter返回的内容"

def __exit__(self, type, value, trace):print("执行了 __exit__方法")

with Test() as test:print("test:", test)

运行结果:

执行了 __enter__方法test: enter返回的内容

执行了__exit__方法

执行过程:

with后面的Test()语句执行、enter()执行

enter()返回值返回给as后面的变量test

执行with语句中间代码块打印变量test、

中间代码块执行完后执行__exit__()

推断:自动关闭文件是在__exit__()中调用文件关闭方法

三、实现支持with的类

open支持with语法,就是因为内部实现了双下enter和双下exit

想让类来使用with就必须支持with语法,即内部实现双下enter和双下exit,如下:

importsysimporttimeimportthreadingclassSpinner:

busy=False

delay= 0.5@staticmethoddefspinning_cursor():while 1:for cursor in '|/-\\':yieldcursordef __init__(self, delay=None):print(111)

self.spinner_generator=self.spinning_cursor()if delay andfloat(delay):

self.delay=delaydefspinner_task(self):whileself.busy:print(333)

sys.stdout.write(next(self.spinner_generator)) #IOprint(999)

sys.stdout.flush()

time.sleep(self.delay) #IOprint(666)

sys.stdout.write('\b')

sys.stdout.flush()print(777)def __enter__(self):print(222)

self.busy=True

threading.Thread(target=self.spinner_task).start()def __exit__(self, exception, value, tb):

self.busy=False

time.sleep(self.delay)if exception is notNone:returnFalse

with Spinner():print(444)

t1=time.time()while time.time()-t1 < 2:print(555)

time.sleep(1) #ioprint('完蛋了')

ContractedBlock.gif

ExpandedBlockStart.gif

111 #执行__init__

222 #执行__enter__

333 #执行任务spinner_task线程1

444|999 #遇到write的io,执行另外的线程2,线程1的io完毕,立即切换回去继续执行线程1输出‘|’

555 #线程1遇到sleep的io立即切换线程2,走到sleep又io,切换回线程1

666

777

333

/999完蛋了555

666

777

333

-999

666

777

333\999完蛋了#时间大于2,线程2的while执行完毕,即with代码块执行完毕,开始执行__exit__,设置退出标志

666

777 #线程1输出完毕,while遇到退出信号也完毕了,大家都完了

结果分析

参考;https://blog.csdn.net/win_turn/article/details/106071154

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值