Як я повинен називати функції, які повертають значення в 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()проти foo.bar()проти foo.bar(припустимо , що fooі barобидва іменників): Перший варіант прямо, тому що «отримати" не додає нічого , що ми вже не знаємо. Другий підходить, якщо barвихід з A foo- це потенційно дорога операція та / або несе побічні ефекти (ви також можете врахувати, Bar(foo)якщо Barце клас). Третя підходить, якщо це дешева операція без побічних ефектів, а альтернативні реалізації навряд чи зроблять її дорогою .
  • xs.sort()vs., sorted(xs)якщо xsє список: Перше обов'язково: Сортування списку. Він змінює список на місці і нічого не повертає. Друга - декларативна: Сортований список, який саме і повертає. Обидва є дієсловами.

[1]: Зазвичай повернення значення та побічні ефекти взаємно виключають, якщо у вас немає певних причин дизайну для їх поєднання. Тож функція, яка має побічні ефекти, ймовірно, нічого не повинна повертати, а значить, іменник має дуже мало сенсу.
[2]: У ioмодулі є кілька помірних операцій нижчого рівня, які можна використовувати для додавання або видалення буферизації файлів, автоматичного en / декодування тексту тощо, і це переважно іменники, оскільки вони об'єктно-орієнтовані класи. Більшості користувачів не потрібно безпосередньо грати з цими речами; натомість open()вибирає відповідний клас та інстанціює його автоматично.


Дякую! У " foo.get_bar() vs.` foo.bar ()` vs. foo.bar" яка різниця між другим і третім ?
Махмуд Мухаммед Нагіб

Третя - або властивість, або голий атрибут. Другий - метод.
Кевін

Тож, якщо я розумію, доречно не робити rotated_letterімперативу і тримати це декларативним, правда?
Махмуд Мухаммед Нагіб

У цьому випадку я не впевнений, чи letterмається на увазі контекст.
Кевін

+1 для згадки list- клас
Dušan Maďar

0

rotated_letterне схожий на метод. Це схоже на власність. Що означає, що перша ідея:

var letter = caesar.rotated_letter

очікуючи letterмістити значення рядка типу, а не функції. Звідти ви вибрали інше ім’я, наприклад:

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, але не прочитав усіх PEPs, і я точно НЕ є експертом. Я не спростував, BTW).
Андрес Ф.

@AndresF: Я відповідаю з точки зору Python. У таких мовах, як Java, де властивостей немає, getSomethingі setSomethingце звичайні імена, що використовуються замість властивостей.
Арсеній Муренко
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.