鱼C论坛

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

[已解决]python 中的with语句

[复制链接]
发表于 2018-5-27 12:35:08 | 显示全部楼层 |阅读模式
20鱼币
  1. with A() as t:
  2.     pass
复制代码

我找到的资料中提及,执行with A() as t时,A()生成一个对象,然后这个对象的__enter__方法被调用,把实例self返回给t。
在退出代码块后,这个实例的__exit__方法被调用。
我写了个A的实现:
  1. class A:
  2.         def __init__(self):
  3.                 print("__init__!")
  4.         def __enter__(self):
  5.                 print("__enter__!")
  6.                 return self
  7.         def __exit__(self, *args):
  8.                 for each in args:
  9.                         print(each)
  10.                 del self
  11.                 print("Now __exit__")
  12.         def func(self):
  13.                 print("Hello!")
复制代码

在__exit__方法中我释放了self这个引用(实际上没必要),但是代码块中我将self赋值给了t,因此这个实例还有一个引用t,不能被回收:
  1. >>> with A() as t:
  2.         pass

  3. __init__!
  4. __enter__!
  5. None
  6. None
  7. None
  8. Now __exit__
  9. >>> t.func()
  10. Hello!
复制代码

问题是,在执行下列代码时:
  1. >>> with open("123.txt", 'w+') as f:
  2.         f.write("Hello")
  3.         f.seek(0)
  4.         f.read()

  5.        
  6. 5
  7. 0
  8. 'Hello'
  9. >>> f.seek(0)
  10. Traceback (most recent call last):
  11.   File "<pyshell#171>", line 1, in <module>
  12.     f.seek(0)
  13. 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-4-19 00:46

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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