2015-09-18 2 views
2

Я немного смущен, меняя (изменяя или добавляя) переменные изнутри функций.
Для справки, я нашел этот вопрос около functions that mutate the argument. который описывает делать только, что на массиве:Python меняет переменные против массивов в функциях?

def add_thing(a): 
    a.append(2) 

my_a = [1] 

append_two(my_a) 
my_a 
>>> [1,2] 

и мы получим те же результаты, используя + = [2]

Однако, если мы попробуем то же самое со строкой, или целым числом:

def add_world (s): 
    s += " world" 

my_str = "hello" 

add_world(my_str) 
my_str 
>>> "hello" 

Он не меняется, и то же самое для целых чисел, например:

def add_one(i): 
    i += 1 

x = 1 
add_one(x) 
x 
>>> 1 

Мой вопрос:

  1. Как узнать, какие объекты я могу мутировать в функции, подобной массиву, и какие из них мне нужно назначить напрямую?

  2. Почему оператор + = не работает, как я ожидал? Я был уверен, что это была короткая рука для my_var = my_var +, которая должна прекрасно работать внутри функции.

+1

Возможный дубликат [Как передать переменную по ссылке?] (Http://stackoverflow.com/questions/986006/how-do-i-pass-a-variable-by-reference) –

+1

Возможный дубликат [Значения списка изменений функций, а не значения переменных в Python] (http://stackoverflow.com/questions/17686596/function-changes-list-values-and-not-variable-values-in-python) –

+1

Прочтите это внимательно, предпочтительно дважды. Это прояснит некоторые вещи для вас. http://robertheaton.com/2014/02/09/pythons-pass-by-object-reference-as-explained-by-philip-k-dick/ –

ответ

2
  1. Вы должны смотреть на документацию. Обычно: числа, строки и tuple s неизменяемы.

    Что касается конкретных методов, существует общее правило: если метод возвращает, то он не изменяет аргумент. Методы, которые изменяют аргумент return None.

  2. a += b соответствует a = a + b, если a является неизменным. Если a изменен, то использование += будет мутировать объект. В основном += - это всего лишь вызов метода (до __iadd__). В случае неизменяемых объектов метод возвращает новый объект и не мутирует исходное значение, для изменяемого объекта объект мутирует и возвращает себя.

2

Как я должен признать, какие объекты можно мутировать в функции как массив, и какие из них мне нужно напрямую назначить?

Вам необходимо знать, какие объекты вы используете, и прочитать документацию для этих объектов, чтобы узнать, какие операции, если они есть, мутируют их. К сожалению, в случае с list это не документировано самым доступным способом. Ближайшая вещь this который говорит:

дополненное выражение присваивания, как x += 1 можно переписать в виде x = x + 1 для достижения таких же, но не точно равного эффекта. В расширенной версии x оценивается только один раз. Кроме того, когда это возможно, фактическая операция выполняется на месте, а это означает, что вместо создания нового объекта и назначения его целевой цели вместо этого изменяется старый объект.

Поскольку списки являются изменяемыми, это означает, что возможна операция на месте.

Почему оператор + = не работает, как я ожидал? Я был уверен, что это была короткая рука для my_var = my_var +, которая должна прекрасно работать внутри функции.

Как видно из приведенной выше цитаты, a += b не совсем то же самое, что a = a + b. Разница в том, что объект a имеет возможность определить специальное поведение для a += b, которое может отличаться от поведения для a + b. Списки делают это так, чтобы += работал на месте.

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