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

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

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

MyObject.save(filename)

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

from myutils import readwrite

readwrite.save(MyObject,filename)

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

13
zenna 17 Авг 2010 в 03:23

2 ответа

Лучший ответ

Кажется, вас беспокоят незакрепленные функции. Это путь питона. Это имеет смысл, потому что модуль в 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), вам придется изменить каждый класс. Если каждый класс реализует интерфейс для получения тех данных, которые он хочет сохранить, то вы можете написать одну функцию для сохранения экземпляров каждого класса и изменить эту функцию только один раз. Это известно как принцип единой ответственности: у каждого класса должна быть только одна причина для изменения.

15
Community 11 Апр 2012 в 02:22

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

3
Tobias Kienzler 10 Авг 2012 в 15:55