Оголосити функцію в кінці файлу в Python


94

Чи можна викликати функцію, не попередньо її повністю визначивши? При спробі цього я отримую помилку: " ім'я_функції не визначено". Я походжу з фону C ++, тому ця проблема мене бентежить.

Оголошення функції перед роботами:

def Kerma():
        return "energy / mass"    

print Kerma()

Однак спроба викликати функцію без її попереднього визначення створює проблеми:

print Kerma()

def Kerma():
    return "energy / mass"

У C ++ ви можете оголосити функцію після виклику, як тільки ви поставите її заголовок перед нею.

Мені чогось тут не вистачає?


5
У Python немає "оголосити". Є визначення (яке повинно бути повним), або там нічого.
S.Lott,

2
Ви кажете: "це завдає клопоту". Чи можете ви детальніше це сказати?
Мартін Дель Веккіо,


На випадок, якщо хтось задається питанням:Kerma is an acronym for "kinetic energy released per unit mass"
anon

1
Я знаю, що це дуже старе, але чому ніхто не рекомендував поміщати функції в окремий .pyфайл та імпортувати це? Чи є якісь ненавмисні наслідки?
Kyle

Відповіді:


145

Одним із ідіоматичних варіантів у Python є написання:

def main():
    print Kerma()

def Kerma():
    return "energy / mass"    

if __name__ == '__main__':
    main()

Це дозволяє писати код у потрібному вам порядку, доки ви продовжуєте викликати функцію mainв кінці.


4
@ Мухаммад: хоча це життєздатний підхід, він, звичайно, не є ідіоматичним у Python. Навпаки, ви помітите, що більшість mainфункцій зазвичай розміщуються в кінці.
Елі Бендерський,

14
@ Елі Бендерскі: Я вважаю, що if __name__ == '__main__':перехід є загальною ідіоматичною частиною.
S.Lott,

2
@Eli: ідіоматичною частиною є речення if в кінці: немає коду на верхньому рівні модуля, тоді в кінці викличте основну функцію, якщо модуль є основним .
Нед Батчелдер,

1
@Eli: Ідіоматичною частиною є if ... __main__':. Я не сказав, що mainслід розміщувати над рештою коду. Я сказав, що важливою частиною є дзвінок _\_main__в кінці, і неважливо, де ви тоді розмістите його визначення.
Мухаммед Алкарурі

2
З if name == ' main ': switch стає неактуальним, як ви впорядковуєте свої функції. Це правильно зробити (TM).
MKesper

18

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

c = a + b  # -> NameError: name 'a' is not defined
a = 13
b = 17

На відміну від багатьох інших мов, defа classоператори виконуються у Python, а не лише декларативні, тому ви не можете посилатися ні на те, aні bдо того, поки це не відбудеться, і вони не будуть визначені. Ось чому ваш перший приклад має проблеми - ви посилаєтесь на Kerma()функцію до того, як її defоператор виконано, а тіло оброблено, а отриманий об'єкт функції прив'язаний до імені функції, тому він не визначений на той момент у сценарії.

Програми такими мовами, як C ++, зазвичай попередньо обробляються перед запуском, і на цьому етапі компіляції вся програма та будь-які #includeфайли, на які вона посилається, читаються та обробляються одночасно. На відміну від Python, ця мова має декларативні оператори, які дозволяють оголошувати (але не визначати) ім'я та послідовність викликів функцій (або статичний тип змінних) перед використанням, так що, коли компілятор зустрічає їх ім'я, він має достатньо інформації для перевірки їх використання, яке в першу чергу передбачає перевірку типу та перетворення типів, жодне з яких не вимагає, щоб їх фактичний вміст або тіло коду ще були визначені.


Це не те, що динамічна мова не може цього зробити. Perl - це динамічна мова, і ви можете викликати функцію, перш ніж визначити її. Це тому, що він має фазу компіляції та фазу виконання (хоч як це не дивно, але корисно, ви можете організувати виконання коду на фазі компіляції). Це працює: doit(); sub doit { print("I'm doing it!\n"); }
Джон Дейган

9

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

Для простих скриптових скриптів звикайте розміщувати "виконувану частину" в кінці, а ще краще - навчіться використовувати інтерактивну оболонку Python.


1

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


1

Якщо ви готові бути схожими на C ++ і використовувати все, що є всередині функцій. Ви можете викликати першу функцію внизу файлу, наприклад:

def main():
    print("I'm in main")
    #calling a although it is in the bottom
    a()

def b():
   print("I'm in b")

def a():
   print("I'm in a")
   b()

main()

Таким чином python спочатку "читає" весь файл, а потім починає виконання

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.