Как мне назвать функции, которые возвращают значения в Python?

13

Я запутался в выборе имен для своих функций в Python . Иногда Python встроенных функций являются императивом , таких как: printфункции и метод строки find. Иногда они не такие, как: lenего имя не является обязательным, как calculate_len, например, и typeне является find_type.

Я могу понять, что printвозвращает значение, которое мы не используем (то есть None) и что-то делает (т.е. показывает строку на экране), поэтому его имя является обязательным.

Но lenвозвращает значение, которое мы используем, и что-то делает (т. Е. Вычисляет, сколько элементов содержится в последовательности или отображении), и его имя не обязательно . С другой стороны, findстроковый метод (as len) возвращает значение, которое мы используем, и что-то делает, и его имя обязательно .

Что заставило задать этот вопрос, так это то, что я поставил скрипт, который шифрует и дешифрует строку с использованием шифра Цезаря, для проверки. Рецензент сказал, что:

Просто интуитивное чувство: функции делают вещи. Поэтому хорошее имя для функции является обязательным: я бы использовал rotate_letterвместо rotated_letter.

rotated_letterвозвращает однобуквенную строку, представляющую букву, повернутую на число. Я не знаю, что лучше, я использовал, rotated_letterпоскольку он возвращает значение, как randintфункция в случайном модуле , это не так generate_randint.

Итак, в этом случае, как я должен назвать функцию, которая возвращает значение, которое будет использоваться? Должен ли я сделать имя обязательным или просто существительным . В других случаях очевидно, как это сделать, например, булевы функции , такие как, is_evenи is_palindromeмы просто делаем это как вопрос «да / нет» , а также функции, которые просто делают и возвращают неиспользуемые значения (то есть None), такие как printи метод списка sort,

Махмуд Мухаммед Нагиб
источник
на самом деле это очень распространенная практика (я бы сказал, соглашение) использовать императивы при именовании функции. Например, как вы называете переменную, в которой хранится повернутая буква функции rotated_letter?
JoulinRouge
Это не очень хороший способ думать о некоторых ваших примерах. lenНапример, о нем лучше думать как о «длине» - вы получаете метауровневое описание его аргумента.
Изката

Ответы:

10

Используйте глаголы, если это разумно, существительные, если они короче и однозначны

В большинстве случаев функции должны быть (обязательными) глаголами и классами, переменные и параметры должны быть существительными. Атрибутами также должны быть существительные, в том числе созданные с использованием @property. Это особенно касается функций, которые имеют побочные эффекты. [1] Если функция что-то возвращает, вы должны оценить, добавляет ли глагол что-то или это просто «шум»:

  • make_list(foo)vs list(foo).: существительное легче читать, чем глагол. Кроме того, listэто на самом деле класс, и классы должны быть существительными.
  • open(foo)vs file(foo).: глагол легче читать, чем существительное, и имеет больше смысла давать «варианты» глаголу, чем существительному, поэтому существительное было удалено в Python 3. open()остается единственным «стандартным» способом [2] создавать файловые объекты в Python 3.
  • foo.get_bar()vs. foo.bar()против foo.bar(предположим, fooи barоба существительные): первый вариант правильный, потому что «get» не добавляет ничего, чего мы еще не знали. Второе уместно, если barвыход из foo- это потенциально дорогостоящая операция и / или сопряженная с побочными эффектами (вы также можете рассмотреть Bar(foo), Barявляется ли класс). Третий вариант подходит, если это дешевая операция без побочных эффектов, а альтернативные реализации вряд ли сделают ее дорогой .
  • xs.sort()vs. sorted(xs)if xs- это список: первое обязательно: отсортируйте список. Он изменяет список на месте и ничего не возвращает. Второй - декларативный: список, который отсортирован, и это именно то, что он возвращает. Оба глаголы.

[1]: Обычно возвращение значения и наличие побочных эффектов являются взаимоисключающими, если только у вас нет веских причин для их объединения. Таким образом, функция, которая имеет побочные эффекты, вероятно, не должна ничего возвращать, и, следовательно, превращение ее в существительное будет иметь мало смысла.
[2]: В ioмодуле есть несколько операций среднего уровня, которые можно использовать для добавления или удаления буферизации файлов, автоматического кодирования / декодирования текста и т. Д., И в основном это существительные, поскольку они являются объектно-ориентированными классами. Большинству пользователей не нужно играть с этими вещами напрямую; вместо этого open()выбирает соответствующий класс и создает его автоматически.

Kevin
источник
Спасибо! В " foo.get_bar() vs.` foo.bar ()` vs. foo.bar чем разница между вторым и третьим ?
Махмуд Мухаммед Нагиб
Третий - это либо свойство, либо голый атрибут. Второй метод.
Кевин
Так что, если я понимаю, уместно не делать rotated_letterимператив и держать его декларативным, верно?
Махмуд Мухаммед Нагиб
В этом случае я не уверен, letterподразумевается ли это под контекстом.
Кевин
+1 за упоминание list- класс
Душан Мажар
0

rotated_letterне похоже на метод. Это похоже на собственность. Это означает, что первая идея заключается в следующем:

var letter = caesar.rotated_letter

ожидая letterсодержать значение типа string, а не функцию. Оттуда вы либо выбрали другое имя, например:

def rotate_letter(self):
    pass

или вместо этого вы используете свойство:

@property
def rotated_letter(self):
    return self.whatever

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

lenособенно хороший пример того, что вы не должны делать в своем коде: вы должны использовать полные имена, такие как length(если короткая форма не очень популярна, например max), и использовать глагол, например compute_length. Или это может быть собственность: len([1, 5, 6])становится [1, 5, 6].length. Например, в C #, используется поздняя форма: new [] { ... }.Length.

Обратите внимание, что могут быть и исторические причины len: другие языки, такие как C #, предпочтительнее Count, что обычно является методом (хотя, к сожалению, поведение несовместимо с .NET Framework). Countэто глагол, так что интуитивно вы склонны вызывать его как метод.

Возврат значений или выполнение действия

Функция всегда должна выполнять действие. Если он едва возвращает значение, это должно быть свойство. У вас есть подсказка, что функция должна быть преобразована в свойство, когда:

  • Функция едва содержит return ...утверждение,

  • Название функции, которое естественно приходит вам на ум get_something, как и в product.get_price().

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

  • Это может быть чисто, то есть возвращать значение, не влияя на окружающую среду. Пример: road.measure_distance().

  • Это может повлиять на окружающую среду, ничего не возвращая. Пример: product_database.remove_record(1234).

  • Это может повлиять на окружающую среду и вернуть значение. Пример: value.increment()используется как value++.

  • Он ничего не может сделать и ничего не вернуть. Пример: time.sleep(1).

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

Арсений Мурзенко
источник
Я предполагаю, что ответ «да», но я должен спросить: вы отвечаете полностью с точки зрения Python? Потому что в других языках разделение функции и свойства не всегда верно; также не верно, что функция «должна выполнить действие». Это соглашение в Python? (Я пишу на Python, но не прочитал все PEP, и я определенно НЕ эксперт. Я не понизил голос, кстати).
Андрес Ф.
@AndresF .: Я отвечаю с точки зрения Python. В таких языках, как Java, где свойства не существуют getSomethingи setSomethingявляются обычными именами, используемыми вместо свойств.
Арсений Мурзенко