python对象file的init_python 3中的文件对象子类化(扩展打开和关闭操作)

tl;dr使用上下文管理器。关于这些问题的重要警告,请参见此答案的底部。

Python 3中的文件变得更加复杂。虽然有一些方法可以在普通用户类上使用,但这些方法不能与内置类一起使用。一种方法是在实例化一个所需的类之前进行混合,但这需要知道类中的混合应该首先是什么:class MyFileType(???):

def __init__(...)

# stuff here

def close(self):

# more stuff here

由于类型太多,将来可能会添加更多类型(不太可能,但可能),而且我们不确定在调用open之后才会返回哪个类型,因此此方法不起作用。

另一种方法是将自定义类型更改为具有返回文件的___bases__,并将返回实例的__class__属性修改为自定义类型:class MyFileType:

def close(self):

# stuff here

some_file = open(path_to_file, '...') # ... = desired options

MyFileType.__bases__ = (some_file.__class__,) + MyFile.__bases__

但这会使Traceback (most recent call last):

File "", line 1, in

TypeError: __bases__ assignment: '_io.TextIOWrapper' deallocator differs from 'object'

另一个可以使用纯用户类的方法是直接从返回实例的类动态创建自定义文件类型,然后更新返回实例的类:some_file = open(path_to_file, '...') # ... = desired options

class MyFile(some_file.__class__):

def close(self):

super().close()

print("that's all, folks!")

some_file.__class__ = MyFile

但是再一次:Traceback (most recent call last):

File "", line 1, in

TypeError: __class__ assignment: only for heap types

因此,看起来在Python3中最有效的方法,幸运的是在Python2中也会有效(如果您希望在两个版本上使用相同的代码基,这很有用)是有一个自定义上下文管理器:class Open(object):

def __init__(self, *args, **kwds):

# do custom stuff here

self.args = args

self.kwds = kwds

def __enter__(self):

# or do custom stuff here :)

self.file_obj = open(*self.args, **self.kwds)

# return actual file object so we don't have to worry

# about proxying

return self.file_obj

def __exit__(self, *args):

# and still more custom stuff here

self.file_obj.close()

# or here

使用它:with Open('some_file') as data:

# custom stuff just happened

for line in data:

print(line)

# data is now closed, and more custom stuff

# just happened

需要记住的一点是:在__init__或__enter__中任何未处理的异常都会阻止__exit__运行,因此在这两个位置,您仍然需要使用try/except和/或try/finally习惯用法来确保您不会泄漏资源。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值