Считается ли Pythonic иметь несколько классов, определенных в одном файле?


31

Работая с python впервые, я обнаружил, что в итоге я пишу несколько классов в одном файле, в отличие от других языков, таких как Java, которые используют один файл на класс.

Обычно эти классы состоят из 1 абстрактного базового класса с 1-2 конкретными реализациями, использование которых незначительно отличается. Я разместил один такой файл ниже:

class Logger(object):

    def __init__(self, path, fileName):
        self.logFile = open(path + '/' + filename, 'w+')
        self.logFile.seek(0, 2)

    def log(self, stringtoLog):
        self.logFile.write(stringToLog)

    def __del__(self):
        self.logFile.close()

class TestLogger(Logger):   

    def __init__(self, serialNumber):
        Logger.__init__('/tests/ModuleName', serialNumber):

    def readStatusLine(self):
        self.logFile.seek(0,0)
        statusLine = self.logFile.readLine()
        self.logFile.seek(0,2)
        return StatusLine

    def modifyStatusLine(self, newStatusLine):
        self.logFile.seek(0,0)
        self.logFile.write(newStatusLine)
        self.logFile.seek(0,2)

class GenericLogger(Logger):

    def __init__(self, fileName):
        Logger.__init__('/tests/GPIO', fileName):

    def logGPIOError(self, errorCode):
        self.logFile.write(str(errorCode))

Как видно выше, у меня есть базовый класс Logger, с парой различий в реализации ниже этого.

Вопрос: это стандарт для python или для любого языка? Какие проблемы могут возникнуть при использовании этой реализации, если таковые имеются?

РЕДАКТИРОВАТЬ: Я на самом деле не ищу руководство по этому конкретному файлу, но в более общем смысле. Что делать, если занятия заканчиваются 3-5 умеренно сложными методами? Есть ли смысл разделять их тогда? Где отсечка, чтобы сказать, что вы должны разбить файл?


3
Ограничение одним классом на файл НЕ является C ++. Я знаю только то, что Java - это то, чего следует избегать. В C ++ очень часто для одного файла .h / .cpp имеется один первичный класс и множество вспомогательных классов, которые могут быть или не быть частными для первичного класса.
Gort the Robot

@ StevenBurnap Я удалил C ++ в качестве примера, как вы правы.
Ampt

1
Это также сделано в php для облегчения автоматической загрузки. С другой стороны, в php вы можете явно объявить пространство имен.
Бодо

Ответы:


24

Все хорошо. Это хорошо в C ++, для справки.

Хранение тесно связанных вещей - разумная практика. Избегание неподходящего соединения также является хорошей практикой. Достижение правильного баланса - это не вопрос строгих правил, а достижение баланса между различными проблемами.

Некоторые практические правила:

  1. Размер

    Чрезмерно большие файлы могут быть некрасивыми, но это вряд ли имеет место. Уродство, вероятно, является достаточно веской причиной для разделения файла, но развитие этого эстетического чувства в значительной степени зависит от опыта, поэтому оно не поможет вам понять, что делать априори.

  2. Разделение проблем

    Если ваши конкретные реализации имеют очень разные внутренние проблемы, ваш единственный файл накапливает все эти проблемы. Например, реализации с неперекрывающимися зависимостями делают ваш отдельный файл зависимым от объединения всех этих зависимостей.

    Таким образом, иногда может быть разумным считать, что связь подклассов с их зависимостями перевешивает их связь с интерфейсом (или, наоборот, проблема реализации интерфейса слабее, чем проблема внутренней реализации).

    В качестве конкретного примера возьмем общий интерфейс базы данных. Конкретные реализации, использующие БД в памяти, СУБД SQL и веб-запрос соответственно, могут не иметь ничего общего, кроме интерфейса, и принуждать всех, кто хочет, чтобы облегченная версия в памяти также импортировала библиотеку SQL, было противно.

  3. Инкапсуляция

    Хотя вы можете писать хорошо инкапсулированные классы в одном и том же модуле, это может привести к ненужному соединению только потому, что у вас есть доступ к деталям реализации, которые иначе не были бы экспортированы за пределы модуля.

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


2
Ваш ответ был бы более убедительным, если бы он ссылался на внешние ссылки, демонстрирующие нормальность объединения классов в одном файле, или предоставляя больше объяснений, указывающих, почему это нормально.

1
Я отредактировал вопрос, чтобы указать, что это просто пример того, что я имею в виду, и он не совсем отражает природу вопроса. Почему хранить их в одном файле лучше, чем просто импортировать их по мере необходимости?
Ampt

Управлять множеством крошечных файлов так же сложно, как и несколькими гигантскими файлами. Python - довольно краткий язык. Ваш пример показывает это. Эти три класса напрямую связаны и, вероятно, помещаются в одном окне редактора без прокрутки.
Gort the Robot

1
@ GlenH7 - я не уверен насчет ссылок, так как они просто отвлекают меня от подачи заявления напрямую, до меня, утверждающего, что моя предвзятость выбора правильна. Вместо этого я попытался сосредоточиться на объяснении.
бесполезно

7

Мои обычные справочные документы, чтобы знать, что такое pythonic.

Простое лучше, чем сложное.

Квартира лучше, чем вложенная.

Из дзен питона

Почти без исключения имена классов используют соглашение CapWords.

Имена пакетов и модулей Модули должны иметь короткие, строчные имена. [...] Имена модулей сопоставляются с именами файлов

Из пп 8

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


7
Не могли бы вы сократить это до частей, имеющих отношение к вопросу? Я прочитал оба из них несколько раз, но мне трудно выбрать, какие части, в частности, относятся к моему текущему вопросу.
Ampt

1
Действительно, я отредактировал свой ответ.
SylvainD

1

То, что у вас есть сейчас, прекрасно. Пойдите и просмотрите стандартную библиотеку - в одном файле есть множество модулей с несколькими связанными классами. В какой-то момент все становится больше, и вы в конечном итоге захотите начать использовать модули с несколькими файлами, но нет никаких реальных правил относительно того, когда. Вещи просто разделяются, когда один файл начинает чувствовать себя «слишком большим».


0

Это определенно хорошо, и я бы посоветовал вам иметь несколько классов в одном файле, если они реализованы. В целом, ваши классы должны быть короткими и лаконичными, и вам лучше разделить поведение на два или более классов, чем строить огромные монолитные. При написании нескольких небольших классов действительно необходимо и полезно хранить те, которые связаны, в одном файле.


-1

Короче - черт возьми, да.

Более того, наличие нескольких классов в одном файле иногда очень удобно. Некоторые пакеты ( six, bottle) явно поставляются в одном файле, чтобы их можно было легко интегрировать в любой сторонний модуль без установки pip (иногда желательно). Но убедитесь, что ваш код организован хорошо. Интенсивно используйте комментарии кода и разделительные блоки, чтобы сделать его более читабельным.


3
это, кажется, не добавляет ничего существенного по сравнению с предыдущим ответом, опубликованным несколько лет назад
комнат
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.