鱼C论坛

 找回密码
 立即注册
查看: 1470|回复: 4

[已解决]python 中的with语句

[复制链接]
发表于 2018-5-27 12:35:08 | 显示全部楼层 |阅读模式
20鱼币
with A() as t:
    pass
我找到的资料中提及,执行with A() as t时,A()生成一个对象,然后这个对象的__enter__方法被调用,把实例self返回给t。
在退出代码块后,这个实例的__exit__方法被调用。
我写了个A的实现:
class A:
        def __init__(self):
                print("__init__!")
        def __enter__(self):
                print("__enter__!")
                return self
        def __exit__(self, *args):
                for each in args:
                        print(each)
                del self
                print("Now __exit__")
        def func(self):
                print("Hello!")
在__exit__方法中我释放了self这个引用(实际上没必要),但是代码块中我将self赋值给了t,因此这个实例还有一个引用t,不能被回收:
>>> with A() as t:
        pass

__init__!
__enter__!
None
None
None
Now __exit__
>>> t.func()
Hello!
问题是,在执行下列代码时:
>>> with open("123.txt", 'w+') as f:
        f.write("Hello")
        f.seek(0)
        f.read()

        
5
0
'Hello'
>>> f.seek(0)
Traceback (most recent call last):
  File "<pyshell#171>", line 1, in <module>
    f.seek(0)
ValueError: I/O operation on closed file.
很明显地看到,在代码块退出后,引用f被自动释放了。我想知道这是如何实现的。。
最佳答案
2018-5-27 12:35:09
本帖最后由 Python小当家 于 2018-5-27 15:23 编辑

这并不是是否释放引用的问题,文件IO有close()方法,只不过在执行__exit__的时候自动执行了close()方法而已,而IO对象一直都在,之所以不能操作,只是因为通道被关闭了。
换句话说,对象一直都在只是换了一种状态。
如图证明,f的引用依然在,依然可以调用方法

最佳答案

查看完整内容

这并不是是否释放引用的问题,文件IO有close()方法,只不过在执行__exit__的时候自动执行了close()方法而已,而IO对象一直都在,之所以不能操作,只是因为通道被关闭了。 换句话说,对象一直都在只是换了一种状态。 如图证明,f的引用依然在,依然可以调用方法
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2018-5-27 12:35:09 | 显示全部楼层    本楼为最佳答案   
本帖最后由 Python小当家 于 2018-5-27 15:23 编辑

这并不是是否释放引用的问题,文件IO有close()方法,只不过在执行__exit__的时候自动执行了close()方法而已,而IO对象一直都在,之所以不能操作,只是因为通道被关闭了。
换句话说,对象一直都在只是换了一种状态。
如图证明,f的引用依然在,依然可以调用方法
捕获.JPG
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2018-5-27 14:57:25 | 显示全部楼层
"""
按照你的思路和题意,我写了相对规范的代码,供你参考。注意:1.出现4个None是因必须4个参数,产生4次循环; 2. with open("123.txt", 'w+') as f:应改为 with A("123.txt", 'w+') as f: 3.“在with代码块开始前调用,返回值与as后参数绑定”和"在with代码块执行后调用,另__exit__括号内必须是4个参数.
"""

class A:
        def __init__(self,name,flag):
             self.filename=name
             self.flag=flag
             print("__init__!")
        def __enter__(self):
             print("在with代码块开始前调用,返回值与as后参数绑定。__enter__!")
             self.f=open(self.filename,self.flag)
             return self.f
        def __exit__(self,*args):
             for each in args:
                 print(each)
             print("在with代码块执行后调用,必须是4个参数。Now __exit__")
             self.f.close()
        def __del__(self):
             print("Hello!")

if __name__=="__main__":
    with A("123.txt", 'w+') as f:
            f.write("python")
            f.seek(0)
            content=f.read()
            print(content)
    print("end")
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

 楼主| 发表于 2018-5-27 19:38:46 | 显示全部楼层
Python小当家 发表于 2018-5-27 12:35
这并不是是否释放引用的问题,文件IO有close()方法,只不过在执行__exit__的时候自动执行了close()方法而已 ...

了解了,谢谢。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

 楼主| 发表于 2018-5-27 19:39:52 | 显示全部楼层
大地0725 发表于 2018-5-27 14:57
"""
按照你的思路和题意,我写了相对规范的代码,供你参考。注意:1.出现4个None是因必须4个参数,产生4次 ...

虽然给了代码,但是下面那位的比较清楚。。还是谢谢啦
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2024-12-26 12:48

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表