Я пишу класс, представляющий файл.Этот класс имеет некоторые дополнительные функции: обычно файлы хранятся в памяти, но иногда необходимо хранить их на диске, иногда я хочу сохранить их в виде zip-файлов и так далее.Я решил использовать миксины, где я могу создать подкласс класса File и в случае необходимости добавить миксины, которые мне действительно нужны в некоторых случаях.В такой ситуации чтение / запись в файл - это операция, которая требует некоторой подготовки и некоторой очистки (мне нужно заархивировать файл, выполнить некоторую запись, например, и затем снова заархивировать обновленную версию).Для этой цели я хотел использовать настраиваемые менеджеры контекста, чтобы гарантировать, что эти действия выполняются, даже если есть оператор исключения или возврата в середине оператора with.Вот мой код:
class File(object):
def read(self):
return "file content"
class ZipMixin(object):
def read(self):
with self:
return super(ZipMixin, self).read()
def __enter__(self):
print("Unzipping")
return self
def __exit__(self, *args):
print("Zipping back")
class SaveMixin(object):
def read(self):
with self:
return super(SaveMixin, self).read()
def __enter__(self):
print("Loading to memory")
return self
def __exit__(self, *args):
print("Removing from memory, saving on disk")
class SaveZipFile(SaveMixin, ZipMixin, File):
pass
f = SaveZipFile()
print(f.read())
Однако вывод весьма разочаровывает:
Loading to memory
Loading to memory
Removing from memory, saving on disk
Removing from memory, saving on disk
file content
, хотя он должен быть:
Loading to memory from disk
Unzipping
Zipping back
Removing from memory, saving on disk
file content
Видимо, все вызовы суперв миксинах с менеджерами контекста не передаются «по цепочке» всем миксинам, а два раза сначала в миксины, а затем напрямую в суперкласс (исключая промежуточные миксины).Я проверил это с Python 2 и 3, тот же результат.Что не так?