在主要方法中,my_object
需要访问passed_object
的多个成员,包括已打开的文件(passed_file = passed_object.create_file()
。例如:
import os
def main():
print('Start of program...')
passed_object = PassedObject()
my_object = MyObject(passed_object)
my_object.use_passed_object()
print('End of program.')
class MyObject(object):
def __init__(self, passed_object):
self.passed_object = passed_object
def use_passed_object(self):
f = self.passed_object.create_file()
print('attribute:')
print(self.passed_object.attr1)
print('contents of first file:')
print(list(f))
class PassedObject(object):
def __init__(self):
self.attr1 = 'some attribute string'
def create_file(self):
path = '/tmp'
files = [file for file in os.listdir(path)
if os.path.isfile(os.path.join(path, file))]
f = open(files[0], 'r')
return f
main()
问题:passed_object
创建my_object
所需的文件对象,以及此简单示例中未显示的其他文件对象。如何在my_object
完成后关闭这些文件对象而不破坏封装?
我看到的潜在解决方案:
不传递passed_object
:传递passed_object.create_file()
和passed_object.attr1
,然后在主with open...
中使用上下文管理器。但是,我现在必须将每个属性/创建的对象传递给my_class
。
编写方法my_object.close_file()
,并从main调用它。这似乎打破了封装,因为主要不应该知道这一点。
编写一个关闭文件的my_object.__del__()
方法。
不要担心关闭它;你的程序会以几行结束。
答案 0 :(得分:1)
假设最简单的情况(因为缺少细节):
PassedObject.create_file
只是打开一个文件,返回它并且不保留对它的引用MyObject.use_passed_object
解决方案很简单:在use_passed_object
完成时关闭文件:
class MyObject(object):
def __init__(self, passed_object):
self.passed_object = passed_object
def use_passed_object(self):
f = self.passed_object.create_file()
try:
print('attribute:')
print(self.passed_object.attr1)
print('contents of first file:')
print(list(f))
finally:
f.close()
或者,由于passed_object.create_file()
只是返回一个支持上下文管理器界面的file
对象,所以你也可以这样做:
def use_passed_object(self):
with self.passed_object.create_file() as f:
print('attribute:')
print(self.passed_object.attr1)
print('contents of first file:')
print(list(f))
在更复杂的场景中(例如,返回了除内置file
以外的其他内容),您可以创建自己的上下文管理器,其封装对passed_object.create_file()
的访问...
另一方面,如果文件在其生命周期中由多个MyObject
方法使用,则需要围绕MyObject
实例的使用情况进行上下文管理。
要做到这一点,你必须:
MyObject
它打开了哪些文件(无论如何都要在多种方法中使用它)MyObject.close
关闭所有这些文件class MyObject(object):
def close(self):
for file_object in self.opened_files:
file_object.close()
然后实现一个上下文管理器并将其用于此目的。
选项1 :使用contextlib.closing
import contextlib
def main():
print('Start of program...')
passed_object = PassedObject()
with contextlib.closing(MyObject(passed_object)) as my_object:
my_object.use_passed_object()
print('End of program.')
选项2 :在MyObject
本身
class MyObject(object):
def __enter__(self):
return self
def __exit__(self, type, value, traceback):
self.close()
def main():
print('Start of program...')
passed_object = PassedObject()
with MyObject(passed_object) as my_object:
my_object.use_passed_object()
print('End of program.')