Как ключевое слово global работает в Canopy IPython?

Рассмотрим следующий фрагмент:

a = ''
def assign(letter):
    global a
    a = letter

Если я загружу это в IDLE и запущу (Python 2.7.6), оно будет вести себя так, как ожидалось:

>>> a
''
>>> assign('b')
>>> a
'b'

Но в IPython, встроенном в Canopy Editor (1.3.1), глобальная переменная не изменяется функцией:

In [2]: a

Out[2]: ''

In[3]: assign('b')

In[4]: a

Out[4]: ''

Это ожидаемое поведение? Как манипулировать глобальными переменными в IPython?

Для справки, я знаю об опасностях глобальных переменных. Я столкнулся с этой проблемой, пытаясь воспроизвести процедуру кэширования, обсуждавшуюся в классе: https://www.youtube.com/watch?v=OgPS2ziCEaw


person Ted Pudlik    schedule 08.06.2014    source источник
comment
это специфическая проблема Canopy, я не могу воспроизвести ее в Ipython.   -  person Padraic Cunningham    schedule 09.06.2014
comment
Возможно, вы import * этот код из модуля?   -  person user2357112 supports Monica    schedule 09.06.2014
comment
Нет, я просто запускаю его. (Честно говоря, я не совсем уверен, что делают IDLE или Canopy, когда вы просите их запустить модуль в интерпретаторе, но я удивлен, что они делают разные вещи!)   -  person Ted Pudlik    schedule 09.06.2014
comment
@PadraicCunningham - вы run фрагмент OP в ipython или просто вводили каждую команду в командной строке ipython?   -  person Jonathan March    schedule 09.06.2014


Ответы (1)


1) IDLE не использует IPython, поэтому сравнение неуместно.

2) Команда run в Canopy помещает стандартную команду ipython %run magic там, где вы можете ее увидеть, в командной строке ipython в Canopy и выполняет ее.

3) То, что вы сообщаете, является нормальным поведением команды ipython run magic. Это немного нелогично при первом знакомстве; краткое объяснение заключается в том, что глобальное пространство имен запускаемого модуля отличается от глобального пространства имен интерпретатора ipython. После запуска модуля его пространство имен копируется в пространство имен интерпретатора (именно поэтому a определено в интерпретаторе), но выполнение функции assign (которая была определена в модуле и чья глобальная команда, следовательно, относится к глобальному пространству имен модуля) , изменяет a в пространстве имен модуля, а не его копию в пространстве имен интерпретатора.

4) Это может показаться излишне запутанным поведением, но цель состоит в том, чтобы убедиться, что модули, запускаемые из командной строки ipython, запускаются «чистыми» от любых обломков, которые могут присутствовать в пространстве имен интерпретатора.

5) Если вы не хотите такого поведения, используйте %run -i mymodule.py, что заставит модуль работать непосредственно в глобальном пространстве имен интерпретатора. Если вы сделаете это, ваш пример будет действовать так же, как Idle. В Canopy самый простой способ сделать это — нажать стрелку вверх в оболочке Python, чтобы вызвать команду %run, а затем отредактировать ее, чтобы вставить -i.

6) Комментатор Padraic выше говорит, что он не может воспроизвести это в ipython. Единственное объяснение, которое я вижу, это то, что он настроил IPython для запуска по умолчанию в режиме -i, или что он на самом деле не запускает фрагмент кода OP, а вместо этого выполняет эти команды непосредственно в интерпретаторе, используя только пространство имен интерпретатора. .

person Jonathan March    schedule 09.06.2014