Как лучше всего упорядочить методы в классе Python?

86

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

Когда я извлекаю методы в Eclipse с помощью PyDev, Eclipse помещает извлеченный метод поверх измененного. Но при этом детали более низкого уровня ставятся перед деталями более высокого уровня. По словам дяди Боба, я должен сделать обратное, чтобы мой код читался как заголовки газет. Когда я программирую на Java, я просто следую его совету.

Что лучше всего подходит для Python?

зетафиш
источник
8
Нет лучшей практики. Делайте то, что имеет наибольший смысл - важные вещи в верхней части - это хорошая идея, а последовательность - это вообще хорошо. PEP-8 не упоминает об этом, и если бы он был высечен в камне, он бы был там.
Гарет Латти,
4
И даже PEP8 не всегда высечен на камне.
Игнасио Васкес-Абрамс
1
Я обычно делаю это группами по функциональности (получение, установка и т. Д.)
CppLearner
Важно отметить, что порядок функций метода может быть произвольным, потому что объявление класса только определяет его функции метода, а не вызывает их. Это позволяет исходному коду подпрограмм методов класса успешно использовать функции методов, которые будут определены позже в листинге.
DragonLord

Ответы:

64

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

  • Сначала интерфейсы: общедоступные методы и магические функции Python определяют интерфейс класса. В большинстве случаев вы и другие разработчики хотите использовать класс, а не изменять его. Таким образом, они будут заинтересованы в интерфейсе этого класса. Помещение его первым в исходном коде позволяет избежать прокрутки деталей реализации, которые вам не нужны.

  • Свойства, магические методы , общедоступные методы: трудно определить лучший порядок между этими тремя, которые являются частью интерфейса класса. Как говорит @EthanFurman, очень важно придерживаться одной системы для всего проекта. Как правило, люди ожидают __init__()лучшей первой функции в классе, поэтому я использую другие магические методы прямо ниже.

  • Порядок чтения: в основном есть два способа рассказать историю: снизу вверх или сверху вниз. Ставя на первое место высокоуровневые функции, разработчик может получить общее представление о классе, прочитав первые пару строк. В противном случае, чтобы получить какое-либо представление о классе, пришлось бы прочитать весь класс, а у большинства разработчиков нет на это времени. Как правило, ставьте методы выше всех методов, вызываемых из их тела.

  • Методы класса и статические методы: обычно это подразумевается порядком чтения, описанным выше. Обычные методы могут вызывать все методы раз и, следовательно, быть первыми. Методы класса могут вызывать только методы класса и статические методы и далее. Статические методы не могут вызывать другие методы класса и идти последними.

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

Данижар
источник
1
Обычно язык не требует упорядочивания. Но у некоторых языков есть общие соглашения. Например, C # StyleCop имеет строгие правила упорядочивания. Для Java см stackoverflow.com/questions/4668218 и т.д.
xmedeko
1
методы класса: они часто используются как конструкторы, а затем обычно вызываются __init__явно (в сочетании с __new__) или неявно (через конструктор по умолчанию), так что это может быть причиной их размещения вместе с __init__. (Хотя я никогда не видел , как они размещены перед __init__ тем .)
oulenz
13

Нет одного правильного порядка. Выберите систему и придерживайтесь ее. Я использую:

class SomeClass(object):
    def __magic_methods__(self):
        "magic methods first, usually in alphabetical order"
    def _private_method(self):
        "worker methods next, also in alpha order"
    def a_method(self):
        "then normal methods, also in alpha order"
Итан Фурман
источник
2
Что вы предпочитаете статическим методам, переменным класса и декорированным методам @property?
Джон Ми
@JohnMee: переменные класса, которые я ставил прежде всего; мой складной метод скрывает @staticmethod, @classmethod, @propertyи любые другие @decoratorстроки , поэтому я использую тип метода , чтобы определить , где он идет (за исключением того, что свойства имеют тенденцию идти между _private_methodsи normal_methods).
Итан Фурман,
Итак, если порядок в основном идет от очень частных «магических» методов к частным и обычным методам, означает ли это, что @classmethods come next ( @classmethod def a_class_method(cls)), а затем @staticmethods ( @staticmethod def a_static_method())? По крайней мере,
такова
2

Я делаю что-то похожее на @Ethan, которое я видел в исходном коде Django, где основное отличие состоит в больших комментариях блока "############" для разграничения областей. Например,

class SomeClass(object):
    #################
    # Magic Methods #
    #################
    def __magic_methods__(self):
        "magic methods first"

    ##################
    # Public Methods #
    ##################
    def a_method(self):
        "then normal methods, in order of importance"

    ###################
    # Private Methods #
    ###################
    def _private_method(self):
        "then worker methods, grouped by importance or related function"

Очевидно, это менее полезно для небольших классов.

Мэтт Луонго
источник
19
Но я вижу, что они волшебные, публичные или частные. Я сам очень не люблю такие блоки комментариев; Я могу посмотреть на свернутый код, если хочу увидеть их все. Я бы сделал комментарий над конкретным блоком методов, связанных с функциональностью, но для этого типа комментариев - это то, что мне говорят названия методов.
Крис Морган
Опять же, я делаю это только для больших классов. Я считаю, что магические методы легко спутать с полуприватными ( ) и именованными (_ ) методами.
Мэтт Луонго,
Я был в середине редактирования, удаляя уродливые ####блоки, когда понял, что вы поместили их туда специально! Однако я согласен с порядком , о чем и идет речь. Я бы рекомендовал удалить ####из этого примера, поскольку он не относится к сфере действия вопроса, а ваш пример относится к небольшому классу, для которого вы все равно не будете использовать ####. :-)
Mateen Ulhaq
1
@MateenUlhaq, пожалуйста, обратитесь к второму и пятому руководству, отображаемому на экране редактирования: «проясняйте смысл, не меняя его» и « всегда уважайте первоначального автора». (Обратите внимание, что они предназначены для безоговорочного применения, без уважения к собственному мнению редактора.) Весь и единственный смысл этого ответа заключался в отображении этих уродливых блоков комментариев; без них он говорит то же самое, что и ответ Итана, и нет никакого смысла здесь быть. Вы даже признали, что блоки были там « специально » - зная это, зачем вам идти и снимать их?
Привет,
1
@MIWright Я думал, что это выходит за рамки вопроса. Как видите, rev2 по- прежнему содержит материал, который отвечает на вопрос иначе, чем у Итана, с другим порядком (и подупорядочиванием!). Тем не менее откатился.
Mateen Ulhaq 09