2013-09-13 2 views
3

Я использую pdb для отладки программы. Я последовательно ударяю 'c', чтобы запустить код, и на каждом шаге pdb показывает мне, какая строка выполняется.python Что происходит при вызове функции?

Допустим, у нас есть этот код:

def foo(bar): 
    print(bar) 

foo('hey') 

Во-первых, линия 4 вызова функции Foo. Затем pdb показывает мне линию

def foo(bar) 

Выполнено.

Почему? Разве это не просто линия ярлыка? Что происходит до выполнения «print (bar)»? (что приходит с чужим ударом)

EDIT: Я экспериментировал, что что-то сделано, чтобы действительно проверить определение. Фактически, в случае, если foo был генератором (который не может быть вызван таким образом), python все еще получает и затем решает рассматривать его как генератор (или функцию, зависящую от случая ...).

+0

Хороший вопрос! Я с нетерпением жду ответа. Я бы сказал, однако, что было бы еще более удивительно, если бы он пропустил. Как еще он будет проверять параметры и т. Д.? (Если он пропустил, как бы он знал, чтобы жаловаться, если вы вызвали 'foo (1, 2)??) – vroomfondel

+0

Да, но мне нужно точно знать, что там происходит. Возможно, вы @rogaos правы. Однако в случае, когда вы предположили, что pdb останавливает свое исполнение в foo (1,2) и никогда не получает строку def. Поэтому, когда мы видим линию def, она уже приняла/соответствовала функции. Обратите внимание, что следующее «попадание» попадает на линию печати и, как всегда, останавливается ** до ** выполнения строки. Таким образом, вы можете проверить стек/кучу, прежде чем что-либо произойдет в функции. –

ответ

8

def не является декларацией в Python, это исполняемый оператор. Во время выполнения он извлекает объект кода, скомпилированный для этой функции, обертывает его в динамически созданный объект функции и связывает результат с именем, следующим за def. Например, рассмотрим этот бесполезный код:

import dis 
def f(): 
    def g(): 
     return 1 
dis.dis(f) 

Вот часть вывода (Python 2.7.5 здесь):

0 LOAD_CONST    1 (<code object g at 02852338, file ...>) 
3 MAKE_FUNCTION   0 
6 STORE_FAST    0 (g) 

Все это, как правило, невидимая деталь, но вы можете играть некоторые малоизвестные трюки с этим ;-) Например, подумайте о том, что делает этот код:

fs = [] 
for i in range(3): 
    def f(arg=i**3): 
     return arg 
    fs.append(f) 
print [f() for f in fs] 

Вот результат:

[0, 1, 8] 

Это потому, что исполняемый файл def создает три отдельных объекта функции, по одному для каждого цикла. Большое удовольствие :-)

1

Что происходит до выполнения «print (bar)»?

Это всего лишь образованное предположение: я предполагаю, что текущий IP-адрес вставляется в стек, а затем параметры. Затем создается новый стек стека, параметры выводятся из стека и добавляются в качестве локальных пользователей в текущую область. Что-то по этой линии.

+0

Звучит разумно. Теперь я сталкиваюсь с конкретной ситуацией, когда что-то не так работает в строке def функции. Программа попадает туда и ... не выполняет функцию! Только с pdb я замечаю сообщение «GeneratorExit: None». Итак, любая догадка о том, что может пойти не так на этом этапе?Примечание. Я пытаюсь сделать минимальный пример, чтобы воспроизвести это, в то время как это казалось интересным вопросом как таковым, и я опубликовал его. –

+0

Итак, получается, что мой генератор не классический. Таким образом, одна вещь, которую он делает, - это проверить, что это такое. http://stackoverflow.com/questions/18777544/dynamic-call-of-functions-and-generator-function-python/18777629?noredirect=1#18777629 –

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