2017-01-27 3 views
1

Я изучаю Python и, более конкретно, изучаю правила обзора.Lexical Scoping в Python

Я попробовал следующий «эксперимент»:

def increment(n): 
    n += 1 
    print(n) 
    return n 

n = 1 
increment(n) 
print(n) 

Этот фрагмент кода выхода: 2, 1. Если не она выдавала вместо 2, 2 с переменной п возвращается в глобальную окружающую среду?

Ваш совет будет оценен по достоинству.

+0

«return' не означает« после этого, измените область действия на глобальную », но значение выражения« increment (n) »будет тогда локальным n. Поэтому вы должны сделать «n = increment (n)». – syntonym

+0

[Здесь] (http://stackoverflow.com/questions/986006/how-do-i-pass-a-variable-by-reference) - все, что вам нужно знать. –

+1

Возможный дубликат [Локальные и глобальные переменные в функциях python] (http://stackoverflow.com/questions/16865213/local-and-global-variables-in-python-functions) – MYGz

ответ

1

Здесь у вас есть две различные переменные (имена): один живет в глобальной области действия, другой локальный - increment. Повторное связывание локального в increment не влияет на глобальное, и тот факт, что increment возвращает его собственный n, также не влияет на глобальный (факт, что у них одно и то же имя, не имеет значения). Если вы хотите иметь глобальный n указывая на значение, возвращенное increment(), вы должны перепривязывают это явно:

n = 1 
print(n) 
n = increment(n) 
print(n) 
1

Рассмотрим следующую модификацию сниппета выше:

def increment(n): 
    n[0] += 1 
    print(n[0]) 
    return n 

n = [1] 
increment(n) 
print(n[0]) 

Печатает 2, 2.

На многих компьютерных языках (среди них Javascript) делается разница между параметрами функции примитива (как целые числа 1 и 2) или соединение (например, одноэлементный список n [0]). Обычно примитивы передаются по значению (их значения копируются во временные переменные, внутренние для функции). Составные объекты обычно не копируются, а передаются по ссылке (адрес объекта передается и объект получает доступ из функции). Если я посмотрю на вывод двух фрагментов кода выше, мне кажется, что Python тоже делает это.

PS После этого я просмотрел a 2009 Stack Overflow question. Первоначальная сущность вызывается в наиболее популярном ответе 2009 неизменяемым объектом, а составная сущность называется изменчивым объектом , в противном случае мой ответ согласуется с более старым ответом.

+0

У Python нет примитивных типов, все объект и изменчивость не отображаются хорошо (например, кортеж является непреложным составным объектом). Также все аргументы передаются с помощью ссылки на объект, ни значения, ни ссылки: https://stackoverflow.com/a/33066581/3001761 – jonrsharpe

+0

Будучи новым для Python, я хотел бы знать, как можно рационализировать разницу в вызове функции increment() со скалярным n или со списком [n]. Разница неоспорима, печатается либо 2,1, либо 2,2. Jonrsharpe, вы знаете, как это объяснить? –

+0

Вы буквально делаете разные вещи. В одном вы мутируете изменчивую структуру данных: 'n [0] = n [0] + 1' (обратите внимание, что нет ничего необычного в том, чтобы возвращать что-то, когда вы мутируете аргумент). В другом вы переназначаете имя из одного неизменяемого объекта в другой, новый неизменяемый объект: 'n = n + 1'. – jonrsharpe