чому потрібна порожня функція


9

Я почав вивчати пітон і мені цікаво, чому потрібна порожня функція в мові програмування

наприклад, у python:

def empty_func():
    pass

навіть у скриптах оболонки порожні функції доступні порожніми функціями.

Моє розуміння та питання:

  1. Чому для мови програмування потрібні порожні функції? Це просто для того, щоб пограти з мовою програмування чи нічого іншого, що насправді має значення?

  2. Якщо це має мету, чи може хтось описати випадок використання чи надати реальний приклад використання порожніх функцій?

  3. Або є якась традиція мови програмування, яка дозволяє порожні функції?


EDIT (речі, які я отримав, читаючи ваші відповіді):

  • Для ескізних алгоритмів або з абстрактними функціями
  • Для надсилання форм без жодної дії не потрібно виконувати
  • Заповнювач місця для деяких обов'язкових операцій

1
їх можна використовувати як STUBS, якщо виконання програми очікує їх знайти / використовувати, однак ви не хочете нічого змінювати через них.
Г.Расовський

Відповіді:


5

У мовах оболонки родини Bourne :команда, яка взагалі нічого не робить, зазвичай використовується у двох ситуаціях:

  • Заповнювач місця, коли щось очікує обов'язкової команди, наприклад

    while some_condtion
    do :
    done

    оскільки doвимагає хоча б однієї команди.

  • Відкидання аргументів, але виконання побічних ефектів всередині списку аргументів, наприклад

    : ${myvar=foo}

Я впевнений, що напевно є й інші програми, про які знають експерти оболонки :)

У Python (та інших мовах) він використовується рідше. Це може виступати аргументом функції вищого порядку, коли ви насправді нічого не хочете робити. Наприклад, скажімо, у вас є функція, яка подає форму і дозволяє асинхронно викликати функцію після завершення подання:

def submit(callback=empty_func):
    ...

Таким чином, якщо callbackце не передбачено, подання все одно буде проходити, але подальші дії не будуть виконуватись. Якщо ви використовували Noneяк значення за замовчуванням, вам доведеться чітко перевірити, чи був зворотний дзвінок None, додавши безлад до коду.


1

Це залежить від того, де ви стоїте в циклі розробки, але іноді, коли накреслюєте алгоритм, ви хочете зробити абстракцію про складні блоки, не реалізуючи їх відразу.

def full_algo():
  init_stuff()
  process_stuff()
  ...

Ви знаєте, як init_stuffбуде працювати, це досить просто в голові, але вам це дійсно не потрібно відразу, тому ви оголошуєте це як порожню функцію. Це дозволить вашому коду збирати та запускати, не турбуючись про деталі горі.

Ще одне використання для випущених додатків - це при використанні спадщини. Припустимо, у вас великий клас, який визначає поведінку конкретного коду платформи. У вас може виникнути логіка, подібна до цієї:

init_filesystem();
access_files();
release_filesystem();

Цей код буде працювати на багатьох платформах, але деякі платформи можуть не потребувати ініціалізації файлової системи. Тоді ваше успадкування буде виглядати приблизно так (віртуальний з = 0 у C ++ означає, що похідні класи ОБОВ'ЯЗКОВО реалізують ці методи):

class FileSystem{
  virtual void init_filesystem() = 0;
  virtual void access_files() = 0;
  virtual void release_filesystem() = 0;
};

Тоді певна реалізація цього класу (інтерфейс) може нічого не робити для деяких із цих методів. Крім того, базовий клас може оголосити порожні методи для init / release замість того, щоб оголосити їх віртуальними.

Нарешті (і соромно), іноді ви підтримуєте дуже старий додаток. Ви побоюєтесь, що видалення методів порушить справи. Це відбувається, коли у вас є складне успадкування, яке не зрозуміло належним чином, або коли у вас є багато покажчиків функцій (зворотних викликів). Ви просто видалите код всередині них, щоб вони все одно викликали, нічого не порушуючи.


0

Rufflewind зробив гарну роботу, коли ви могли використовувати порожню функцію в завершеній програмі. На мій досвід, це, як правило, частіше використовується в незавершених програмах, тож ви можете планувати, що ви збираєтеся написати, і мати все ще компілювати, поки не обійдетеся з реальною реалізацією. Іншими словами, зазвичай це просто заповнювач.

Це потрібно у випадку python, оскільки він використовує відступ для позначення блоків, на відміну від мов, подібних С, які використовують дужки {}. Це означає, що якщо у вас цього не було pass, аналізатор не міг би визначити, чи маєте ви намір залишити його порожнім або ви забули. Включення passробить аналізатор набагато простішим і дає вам зручне слово для пошуку, коли ви шукаєте невтілені блоки.


1
Для незакінченого коду кидання NotImplementedErrorє більш адекватним рішенням, оскільки "Помилки ніколи не повинні проходити мовчки", а виклик нереалізованої функції в прямій програмі є помилкою.
ivan_pozdeev

Це залежить. Що стосується коду, який ви відправляєте, так. Але якщо це код, який ви очікуєте впровадити за годину, і ви просто залишаєте його без виконання, працюючи над тестовими одиницями, просто не залишаючи жодної реалізації, це може бути кращим варіантом. Часто мій робочий процес: 1) метод запису заглушки з pass 2) записування одиничного тесту, що тестує повернене значення 3) перевірка тесту не вдається (як метод повертає невизначене) 4) впровадити метод 5) перевірити тест зараз проходить
Gort the Robot

0

Хоча це не те, що ви очікували б зробити в Python, у світі є драйвери пристроїв, коли вам потрібно надати порожню функцію, щоб обробити подію, про яку ви (а) знаєте, що не відбудеться або ( б) байдуже, навіть якщо це так.

Ви також бачите це на C із зворотними дзвінками. Іноді ви побачите код, який просто ЗАБЕЗПЕЧИТИ, що ви поставили зворотний дзвінок, і намагатиметесь викликати його, ігноруючи ризик виникнення нульового вказівника. Все, що ви можете зробити в цьому випадку - це подати порожню процедуру зворотного виклику. (Так, я маю на увазі конкретного постачальника.)


Я passбагато використовував як заповнювач при написанні коду, особливо на заняттях, коли мені хочеться чогось запуску, перш ніж все буде завершено. Це дійсно еквівалент python {}, який python не може зробити, оскільки він не використовує дужки. У цьому сенсі всі мови, які я знаю, дозволяють це зробити, це лише те, що лише пара, як, наприклад, pythonпотребує ключового слова. Навіть у дні складання у нас були NOP.
Gort the Robot

@StevenBurnap, зазвичай, коли я роблю щось подібне, я включаю локальний еквівалент printf (">>> звичайний XXX, який називається \ n");
Джон Р. Стром
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.