2017-02-22 23 views
2

Я пишу модуль, который преобразует несколько различных форматов файлов (например, vhdl в verilog, excel table в vhdl и т. Д.). Это не так сложно, но есть много специфического для языка форматирования. Мне просто пришло в голову, что элегантный способ сделать это состоял в том, чтобы иметь тип класса для каждого типа формата файла, имея класс, построенный на file.io. Класс наследует методы файла, а также возможность читать или писать определенный синтаксис для этого файла. Я не мог найти никаких примеров файла io суперкласс и как его написать. Моя идея состояла в том, что его экземпляр (открыть файл) я мог бы использовать:Как создать класс, основанный на файле.io

my_lib_file = Libfile(filename, 'w') 

и написать простой параметр в libfile я мог бы использовать что-то вроде

my_lib_file.simple_parameter(param, value) 

Такой класс должен связать вместе многие специфичные для файла функции, которые я сейчас использую аккуратно. На самом деле я бы предпочел, чтобы иметь возможность создать экземпляр класса как часть с заявлением например .:

with Libfile(filename, 'w') as my_lib_file: 
    for param, value in my_stuff.items(): 
     my_lib_file.simple_parameter(param, value) 
+1

У вашего класса будет две обязанности, которые должны быть красным. –

+0

На данный момент я сделал гибридное решение, которое всего 2 линии, так что это не так плохо, но моя оригинальная идея более аккуратная. @PeterWood, пожалуйста, объясните, почему вы думаете, что моя оригинальная идея приведет к тому, что у вас есть две обязанности? –

+0

Его обязанности - форматировать вывод и вести себя как файл. –

ответ

3

Это неправильный способ думать об этом.

Вы наследуете, чтобы быть повторно использованными. Базовый класс предоставляет интерфейс, который другие могут использовать. Для файловых объектов в основном это read и write. Но вы хотите только вызвать другую функцию simple_parameter. Вызов write напрямую может испортить формат.

Действительно, вы не хотите, чтобы это был файл-подобный объект. Вы хотите записать файл, когда пользователь называет simple_parameter. Реализация должна делегировать в файл типа объекта члена вместо этого, например:

class LibFile: 
    def __init__(self, file): 
     self.file = file 

    def simple_parameter(self, param, value): 
     self.file.write('{}: {}\n'.format(param, value)) 

Это легко проверить, как вы могли бы пройти в то, что поддерживает write:

>>> import sys 
>>> lib = LibFile(sys.stdout) 
>>> lib.simple_parameter('name', 'Stephen') 
name: Stephen 

редактировать:

Если вы действительно хотите, чтобы класс управлял временем жизни файла, вы можете предоставить функцию закрытия и использовать контекстный менеджер closing:

class Formatter: 
    def __init__(self, filename, mode): 
     self.file = open(filename, mode) 

    def close(self): 
     self.file.close() 

Использование:

class LibFormatter(Formatter): 
    def simple_parameter(self, param, value): 
     self.file.write('{}: {}\n'.format(param, value)) 

from contextlib import closing 

with closing(LibFormatter('library.txt', 'w')) as lib: 
    ... # etc 

второй править:

Если вы не хотите использовать closing, вы можете написать свой собственный менеджер контекста:

class ManagedFile: 
    def __init__(self, filename, mode): 
     self.file = open(filename, mode) 

    def __enter__(self): 
     return self 

    def __exit__(self, *args): 
     self.close() 

    def close(self): 
     self.file.close() 

Использование:

class LibFormatter(ManagedFile): 
    def simple_parameter(self, param, value): 
     self.file.write('{}: {}\n'.format(param, value)) 

with LibFormatter('library.txt', 'w') as lib: 
    ... # etc 
+0

ОК, Спасибо за ответ. Это похоже на то, что я уже написал в своем ответе, но я бы предпочел использовать синтаксис и автоматически закрыть файл. Есть ли синтаксис, который позволил бы мне это сделать? Думаю, мне тоже пришлось бы написать свою собственную функцию? –

+1

Обновлено. Вероятно, вы должны обновить вопрос, чтобы сказать, что именно вы действительно искали. –

+0

Спасибо за редактирование. Это приближается к моей оригинальной идее. Я обновил вопрос, чтобы показать свое предпочтительное использование с помощью инструкции with. Contextlib является новым для меня и будет новым для других в моей группе, поэтому я предпочел бы сделать тяжелый подъем один раз и обеспечить чистый интерфейс для класса, вместо того, чтобы обертывать экземпляр в функции закрытия. Его хорошо изучать новые вещи: o) –

0

Моего два решения строки выглядит следующим образом:

with open(lib_loc + '\\' + lib_name + '.lib', 'w') as lib_file_handle: 
    lib_file = Liberty(lib_file_handle) 
    # do stuff using lib_file 

инициализация класс выглядит следующим образом:

def __init__(self, file): 
    ''' associate this instance with the given file handle ''' 
    self.f = file 

теперь вместо прохождения сырого дескриптора файла я прохожу класс вместе с функциями для выполнения своих функций.

Простейшая функция:

def wr(self, line): 
    ''' write line given to file''' 
    self.f.write(line + '\n') 

Что означает, что я тиражирование функцию записи, встроенный в класс file.io. Этого я и пытался избежать.

+0

Это не отвечает на ваш вопрос (c: –

 Смежные вопросы

  • Нет связанных вопросов^_^