Я испытываю головную боль, пытаясь понять, как организовать модули и классы вместе. Исходя из C ++, я привык к классам, инкапсулирующим все данные и методы, необходимые для обработки этих данных. Однако в python есть модули, и из кода, на который я смотрел, некоторые люди имеют много свободных функций , хранящихся в модулях, тогда как другие почти всегда связывают свои функции с классами как методы.
Например, скажем, у меня есть структура данных, и я хотел бы записать ее на диск.
Одним из способов было бы реализовать метод сохранения для этого объекта, чтобы я мог просто напечатать
MyObject.save(filename)
или что-то в этом роде. Другой метод, который я видел в равной пропорции, - это получить что-то вроде
from myutils import readwrite
readwrite.save(MyObject,filename)
. Это небольшой пример, и я не уверен, насколько конкретно эта проблема связана с питоном, но мой общий вопрос - какова лучшая практика с точки зрения питона? функций против методов организации?
Похоже, вас беспокоят незакрепленные функции. Это путь питона. Это имеет смысл, потому что модуль в 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-файл), вам придется изменить каждый класс. . Если каждый класс реализует интерфейс для получения тех данных, которые он хочет сохранить, то вы можете написать одну функцию для сохранения экземпляров каждого класса и изменить эту функцию только один раз. Это известно как принцип единой ответственности: у каждого класса должна быть только одна причина для изменения.
Если у вас есть обычный старый класс, который вы хотите сохранить на диск, я бы просто сделал его методом экземпляра. Если бы это была библиотека сериализации, которая могла бы обрабатывать разные типы объектов, я бы поступил вторым способом.