2013-07-30 2 views
1
$ cat declare_funcs.py 
#!/usr/bin/python3 

def declared_after(): 
     print("good declared after") 

declared_after() 

$ python3 declare_funcs.py 
good declared after 

Изменить место вызова:Декларация функции питона после вызова

$ cat declare_funcs.py 
#!/usr/bin/python3 

declared_after() 

def declared_after(): 
     print("good declared after") 

$ python3 declare_funcs.py 
Traceback (most recent call last): 
    File "declare_funcs.py", line 4, in <module> 
    declared_after() 
NameError: name 'declared_after' is not defined 

Есть ли способ объявить только заголовок функции, как это было в C/C++?

Например:

#!/usr/bin/python3 

def declared_after() # declaration about defined function 

declared_after() 

def declared_after(): 
     print("good declared after") 

Я нашел это Declare function at end of file in Python

В любом случае появляется еще одна функции в начале, как обертки, и эта обертка должна быть вызвана после объявления обернутой функции, это не является Выход. Есть ли еще элегантный true-python way?

+3

Ответ в решении, который вы связали, является как питоническим, так и элегантным. –

+0

Другой дублирующий вопрос: http://stackoverflow.com/questions/1590608/is-it-possible-to-forward-declare-a-function-in-python – 2rs2ts

ответ

4

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

Это, конечно же, не означает, что код не скомпилирован до начала исполнения - фактически, это так. Но когда выполняется def, то на самом деле declared_after присвоен код в блоке def, а не раньше.

Любые трюки, которые вы пытаетесь выполнить для достижения желаемого эффекта, должны иметь эффект отсрочки вызова до declared_after() до тех пор, пока он не будет определен, например, путем помещения его в другой блок def, который сам называется позже.

1

Одна вещь, которую вы можете сделать, это вложить все, что в главной функции:

def main(): 
    declared_after() 

def declared_after(): 
    print("good declared after") 

main() 

Однако точка все еще стоит, что функция должна быть определена перед вызовом. Это работает только потому, что main называется ПОСЛЕ declared_after.

0

Как пишет zigg, файлы Python выполняются для того, чтобы они записывались сверху вниз, поэтому даже если бы вы могли «объявить» переменную раньше, фактическое тело функции будет доступно только после вызова функции.

Обычный способ решить эту проблему, чтобы просто иметь main функцию, где все ваши стандартные вещи исполнение происходит:

def main(): 
    # do stuff 
    declared_after(); 

def declared_after(): 
    pass 

main() 

Вы можете также совместить это с __name__ == '__main__' idiom сделать функцию только выполнить, когда вы прямое выполнение модуля:

def main(): 
    # do stuff 
    declared_after(); 

def declared_after(): 
    pass 

if __name__ == '__main__': 
    main() 
2

Вы не можете переслать функции в Python. Это не имеет большого смысла, потому что Python динамически типизирован. Вы могли бы сделать что-то глупое, как это, и что можно ожидать от этого?

foo = 3 
foo() 
def foo(): 
    print "bar" 

Очевидно, что вы пытаетесь __call__int объекта на 3. Это абсолютно глупо.

Вы спрашиваете, можете ли вы форвард-объявить, как в C/C++. Ну, вы обычно не запускаете C через переводчика. Однако, хотя Python равен compiled to bytecode, программа python3 является интерпретатором.

Форвардное объявление на скомпилированном языке имеет смысл, потому что вы просто устанавливаете символ и его тип, а компилятор может несколько раз пропустить код, чтобы понять его. Однако, когда вы используете интерпретатор, вы, как правило, не можете обладать этой роскошью, потому что вам нужно будет пропустить оставшуюся часть кода, чтобы найти смысл этого форвардного объявления, и пропустите его снова, выполнив это.

Вы можете, конечно, сделать что-то вроде этого:

foo = lambda: None 
foo() 
def foo(): 
    print "bar" 

Но вы инстанцирован foo тем не менее. Все должно указывать на фактический, существующий объект в Python.

Это не относится к def или class операторам. Они создают объект function или class, но они еще не выполняют код внутри. Таким образом, у вас есть время для создания объектов внутри них до того, как их код будет запущен.

def foo(): 
    print bar() 
# calling foo() won't work yet because you haven't defined bar() 
def bar(): 
    return "bar" 
# now it will work 

Разница в том, что вы просто создали function объекты с именами переменных foo и bar представляющих их соответственно. Теперь вы можете ссылаться на эти объекты по этим именам переменных.

Что касается способа интерпретации Python (в CPython), вы должны убедиться, что вы не выполняете код в своих модулях, если они не запускаются в качестве основной программы или если вы не хотите, чтобы они что-то делали при импорте (редкий, но действительный случай). Вы должны сделать следующее:

  1. Положить код, предназначенный для выполнения функций и определений классов.
  2. Если код не имеет смысла быть выполненным в основной программе, поместите его в другой модуль.
  3. Используйте команду if __name__ == "__main__":, чтобы создать блок кода, который будет выполняться только в том случае, если программа является основной программой.

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

if __name__ = "__main__": 
    pass 

Это предотвращает что-нибудь случиться, если модуль импортируется.

Смежные вопросы