В Python функции - это данные, а типизация - динамическая.Это означает, что следующие строки действительны Python:
def func(x):
return x + 3
func = 3
func
теперь является внутр. Исходная функция func
больше не ссылается. Тот факт, что func
изначально был функцией, не имеет никакого отношения к тому, какие типы данных могут быть присвоены ему в будущем. (Это то, что означает «динамическая типизация»).
Поэтому, поскольку нет статического ввода, а «функция» является допустимым типом данных, интерпретатор Python не имеет смысла различать функцию и кусок данных, на которые ссылается одноименное имя. Поэтому в рамках данной области невозможно использовать одно и то же неквалифицированное имя переменной, чтобы обозначать две разные вещи.
В вашем конкретном случае, если код в вашей xplus1
функции означает, что-нибудь, это будет означать «вычислить значение xplusy(x,1)
и назначить того, что значение переменной xplusy
- тем самым теряя ссылку на функцию xplusy
«. Тем не менее, в рамках функции интерпретатор не позволит вам назначить переменную за пределами этой области, поэтому предполагает, что, написав инструкцию присваивания, вы вводите новую локальную переменную xplusy
. Однако локальная переменная еще не определена, поэтому ваша попытка называть ее, xplusy(x,1)
, терпит неудачу. Глобально определенная функция не вызывается как спад, потому что, опять же, вы не можете иметь два неквалифицированных имени одинаково и указывать на разные данные в той же области.
Другой пример не демонстрирует «отсутствие дублирования имен переменных в пределах одной сферы» правил (которые я на самом деле только обнаруженных во время игры вокруг с подсказкой в моей попытке построить этот ответ):
>>> def f1():
... a = xplusy(3,4)
... xplusy = 5
... print xplusy
...
>>> f1()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 2, in f1
UnboundLocalError: local variable 'xplusy' referenced before assignment
>>> def f1():
... a = xplusy(3,4)
... print a
...
>>> f1()
7
Это демонстрирует, что это действительно сфера, а не заявление, требующее уникальных имен.
EDIT: Это действительно здорово, что сообщение объясняет это и другое поведение рамочный связанные: http://me.veekun.com/blog/2011/04/24/gotcha-python-scoping-closures/
Почему усложнять свою жизнь? Просто дайте ему другое имя. – Maroun
Вы можете просто «возвращать xplusy (x, 1)», например: 'def xplus1 (x): return xplusy (x, 1)' –
Часто бывает полезно делать и широко использовать на других языках. Это не проблема, чтобы изменить его, но если речь идет о добавлении пары символов в код, я в порядке с ним. Почему это происходит теоретически, также неясно мне ... – sashkello