Подтвердить что ты не робот

Порядок выполнения и стиль кодирования в Python

Я новичок в Python, поэтому, пожалуйста, не плачьте, если вопрос слишком прост:)

Я прочитал, что Python выполняется сверху вниз.

Если это так, почему программы идут так:

def func2(): 
    pass

def func1():
    func2()

def func():
    func1()

if __name__ == '__main__':
    func()

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

Я не прав, говоря это? Если нет, то почему не основная функция или определения функций, написанные сверху вниз?

EDIT: Я спрашиваю, почему я не могу этого сделать:

if __name__ == '__main__':
    func()

def func1():
    func2()

Разве это не естественный порядок? Вы продолжаете добавлять вещи внизу, поскольку они выполняются сверху вниз.

4b9b3361

Ответ 1

def просто создают функции. Код не выполняется, за исключением синтаксического анализа синтаксиса и привязки функций к этим именам.

if - это первый код места, который фактически выполняется. Если вы поставите его первым и вызовете функцию до ее определения, результатом будет NameError. Поэтому его нужно поставить после определения функций.

Обратите внимание, что это не похоже на PHP или JavaScript, где функции "подняты" - любые определения функций обрабатываются и анализируются перед всем остальным. В PHP и JavaScript совершенно законно делать то, что вы говорите, и определять функции в источнике ниже, чем там, где они вызываются. (Одна деталь в JS - то, что функции, определенные как function(){}, подняты, в то время как функции, определенные как var func1=function(){}; - нет. Я пока не знаю, как это работает с анонимными функциями в PHP 5.3).

Смотрите, здесь cat() будет печататься правильно, а yip() дает вам NameError, потому что синтаксический анализатор не получил определение yip() во время его вызова.

def cat():
  print 'meowin, yo'

cat()

yip()

def yip():
  print 'barkin, yall'

мяу, лет
Traceback (последний вызов был последним):
 Файл "cat.py", строка 5, в
   Yip()
NameError: имя 'yip' не определено

Ответ 2

Python выполняется сверху вниз, но выполнение блока "def" не выполняет сразу же содержащийся код. Вместо этого он создает объект функции с заданным именем в текущей области. Рассмотрим файл Python, похожий на ваш пример:

def func2():
    print "func2"

def func1():
    func2()

def func():
    func1()

if __name__ == '__main__':
    func()

Что происходит, когда этот script выполняется, выглядит следующим образом:

Во-первых, создается объект функции и привязывается к имени "func2" в глобальной области. Затем создается объект функции и привязывается к имени "func1" в глобальной области. Затем один называется "func" . Затем выполняется оператор "if", условие истинно и выполняется оператор "func()". На данный момент "func" - это объект функции, найденный в глобальной области, поэтому он вызывается и его код запускается. Этот код содержит оператор "func1()", который разрешен для вызова функции "func1" и т.д.

Если вы помещаете оператор "if" наверху, тогда, когда он выполняется, еще не будет ничего определенного с именем "func" , поэтому вы получите ошибку. Важно отметить, что оператор "def" сам является выражением, которое выполняется. Это не похоже на некоторые другие языки, где определения представляют собой отдельный вид объявления без порядка выполнения.

Также обратите внимание, что до тех пор, пока бит "if __name__..." находится в конце файла, на самом деле не имеет значения, в каком порядке находятся другие объявления, поскольку к тому времени, когда будет вызван любой из них все "def" будут уже выполнены.

Ответ 3

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

В вашем примере интерпретатор Python выполняет следующие шаги:

  • Определить func2.
  • Определить func1.
  • Определить func.
  • Обработать оператор if if __name__ == '__main__':.
  • Вызвать функцию func (поскольку условие истинно).
  • Вызвать функцию func1 (потому что это делает func).
  • Вызвать функцию func2 (потому что это делает func1).
  • Закончить, потому что после завершения вызова func2 он также завершил вызов func1 и, следовательно, завершил вызов func, который был последним в коде.

Ответ 4

Часть if __name__ == "__main__" идет в конце, потому что, предположительно, что бы ни делала ваша основная функция, потребуются все другие определения в script. Если бы были какие-либо другие определения функций ниже основного блока, тогда их было бы невозможно использовать, поскольку они не были замечены интерпретатором в этой точке.

Ответ 5

Операторы

def просто определяют функцию - они фактически не запускают ее до тех пор, пока не будет вызвана функция. Следовательно, почему они обычно поступают до того, как какой-либо код использует их - они устанавливают функцию, которая будет использоваться в будущем.

Нет жесткого требования, чтобы операторы def приходили раньше всего, довольно просто поставить код __main__ внизу (между прочим, он дает понять, что в этом разделе, а что нет, поскольку все, что находится ниже if, является частью этого раздела). Он также гарантирует, что все, что вы хотите вызвать из раздела, уже было def 'd.

Ответ 6

Для второй части вашего вопроса (стиль кодирования в Python) я хотел бы взглянуть на PEP 8, который обеспечивает написанный Гвидо ван Россумом (сам BFDL!) и содержит основы написания питонического кода.

Ответ 7

Верно, что соглашение состоит в том, чтобы поместить "главную" функцию чуть выше инструкции "if __name__ == '__main__'" в конце файла. Я думаю, что это потому, что мы обычно хотим, чтобы функции находились рядом с их вызывающими сайтами.

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

Это всего лишь примитивная форма организации кода. Если есть более сильная связная единица, у меня возникнет соблазн вытащить эти функции в их собственный модуль.

Ответ 8

Стоит также отметить, что вы можете записывать вызовы функций "до того, как они будут определены", если они не выполняются. Упоминание этого здесь как распространенная ошибка новичка в python. Ни один из других примеров не демонстрирует такое поведение "все в порядке, с одной стороны". (хотя не очень рекомендуется)

def hi():
  pie()

#hi() cannot be called here, does not work because hi depends on pie

def pie():
  print('hi pie')

hi() # it ok to call here!

Вы даже можете пойти немного дальше (немного глупый пример, но я полагаю, это проясняет пример)

runIt = False
def hi():
  if runIt:
    pie()

hi() #now ok, as the code won't call pie.
runIt = True
#hi() #wouldn't be ok as now the code will call pie.

def pie():
  print('hi pie')

hi() # ok here too!