Организация классов и модулей в python

Я получаю немного головную боль, пытаясь понять, как организовать модули и классы вместе. Исходя из С++, я использую классы, инкапсулирующие все данные и методы, необходимые для обработки этих данных. В python есть модули, но из кода, на который я смотрел, у некоторых людей есть много свободных функций, хранящихся в модулях, тогда как другие почти всегда связывают свои функции с классами как методы.

Например, у меня есть структура данных и вы хотите записать ее на диск.

Один из способов - реализовать метод сохранения для этого объекта, чтобы я мог просто набрать

MyObject.save(filename)

или что-то в этом роде. Другой метод, который я видел в равной пропорции, - это что-то вроде

from myutils import readwrite

readwrite.save(MyObject,filename)

Это небольшой пример, и я не уверен, что проблема с python связана с этой проблемой вообще, но мой общий вопрос заключается в том, что является лучшей питонической практикой в ​​плане функций против организации методов?

Ответ 1

Кажется, что вам нужны свободные функции. Это путь python. Это имеет смысл, потому что модуль в python - это действительно просто объект на той же основе, что и любой другой объект. У него есть поддержка уровня языка для загрузки из файла, но кроме этого, это просто объект.

поэтому, если у меня есть модуль foo.py:

import pprint

def show(obj):
    pprint(obj)

Затем, когда я импортирую его из bar.py

import foo

class fubar(object):
   #code

   def method(self, obj):
       #more stuff
       foo.show(obj)

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

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

Рациональным для точного примера, который вы указали, является то, что если у каждого класса есть метод сохранения, то если позже вы измените способ сохранения данных (например, файловая система в базу данных или удаленный XML файл), вы должны изменить каждый класс, Если каждый класс реализует интерфейс для получения данных, которые он хочет сохранить, вы можете написать одну функцию для сохранения экземпляров каждого класса и только однократно изменить эту функцию. Это известно как принцип единой ответственности: у каждого класса должна быть только одна причина для изменения.

Ответ 2

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