2012-03-15 1 views
5

Я смущен ссылкой на Python. Рассмотрим следующий пример:Как работает ссылка Python?

Моя задача: Чтобы изменить каждый элемент в списке

d = { 'm': [1,2,3] } 
m = d['m'] 
m = m[1:] # m changes its reference to the new sliced list, edits m but not d (I wanted to change d) 

Аналогично:

d = { 'm': [1,2,3] } 
m = d['m'] 
m = m[0] # As per python referencing, m should be pointing to d['m'] and should have edited d 

В питоне все идет по ссылке, а затем, когда новый объект создан? Нужно ли нам copy и deepcopy от copy модуль для копирования объектов?

Просьба уточнить.

+1

Если вы визуальный ученик, [здесь] (http://people.csail.mit.edu/pgbovine/python /) хороший учебник – forivall

+0

Чрезвычайно полезный комментарий Mr. @jordoex - Серьезно Удивительный! –

ответ

11

В Python переменная не является полем, в котором содержатся вещи, это имя указывает на объект. В коде:

  • d = { 'm': [1,2,3] } -> связывает имя d к словарю
  • m = d['m'] -> связывает имя m к списку
  • m = m[1:] -> связывает имя m в другой список

Ваша третья строка не меняется m сама, но то, что указывает m.

Для редактирования элементов в списке, что вы можете сделать, это:

m = d['m'] 
for i, item in enumerate(m): 
    result = do_something_with(item) 
    m[i] = result 
+0

Есть ли другой способ редактировать каждый элемент этого списка, кроме 'enumerate'? –

+0

«Имя, указывающее на объект», может быть запутанным, поскольку «указатель» не является терминологией Python. Я бы просто сказал «это имя для объекта». –

+0

«Ваша третья строка не меняет сам, но то, что m указывает на», может быть немного непонятным для читателя. Чтобы быть более явным: «третья строка изменяет m на указание одной вещи (d ['m']) на указание на другую вещь ([2,3])». –

5

Ethan Furman проделали отличную работу, объясняя, как Python Internals работу, я не буду повторять.

С m действительно представляет список внутри словаря, вы можете его изменить. Вы просто не можете переназначить его на что-то новое, что происходит, когда вы используете =, чтобы приравнять его к новому фрагменту.

Чтобы отрезать первый элемент списка, например:

>>> m[0:1] = [] 
>>> d 
{'m': [2, 3]} 
+4

Ненавижу диск от downvotes, если я сделал что-то не так, мне нравится выяснять, почему. Этот ответ был протестирован в Python 2.7 с использованием рекомендуемой идиомы: http://docs.python.org/library/stdtypes.html#mutable-sequence-types –

+0

Я думаю, что это хороший проницательный знак, и я не знаю, почему он был downvoted ... –

+2

Чтобы удалить элементы или фрагменты из списка, я обычно предпочитаю более явный 'del m [0]'. Конечно, это стилистическое предпочтение, и я понятия не имею, почему кто-то забыл. Я предполагаю, что многие из этих, казалось бы, случайных downvotes являются результатом слишком малых дисплеев смартфонов. –

4

В питоне все идет по ссылке

В Python, весь является ссылкой и ссылки переходите по значению.

Если вы хотите использовать эти термины. Но эти условия усложняют понимание.

Гораздо проще: в Python переменная является именем для объекта. = используется для изменения имени объекта. Левая часть может относиться к части существующего объекта, и в этом случае весь объект изменяется путем замены этой части. Это связано с тем, что объект, в свою очередь, на самом деле не содержит его частей, но вместо этого содержит больше имен, которые могут быть вызваны, чтобы начать ссылаться на разные вещи.

тогда, когда новый объект создан?

Объекты создаются при их создании (с использованием конструктора классов или в случае встроенных типов, имеющих литеральное представление, путем ввода литерала). Я не понимаю, как это относится к остальной части вашего вопроса.

m = m[1:] # m changes its reference to the new sliced list 

Да, конечно. Теперь m относится к результату оценки m[1:].

edits m but not d (I wanted to change d) 

Да, конечно. Почему будет это изменение d? Это была не какая-то магия, а просто результат оценки d['m']. Точно одно и то же происходит на обеих линиях.

Давайте рассмотрим более простой пример.

m = 1 
m = 2 

ли это причиной 1 стать 2? Нет, конечно нет. Целые числа неизменны. Но то же самое происходит: m призван назвать одно, а затем назвать другое.

Или, еще один способ: если «ссылки» должны работать так, как вы ожидаете, строка m = m[1:] будет рекурсивной. Вы ожидаете, что это означает «где-нибудь, что вы видите m, относитесь к нему так, как если бы это означало m[1:]». Ну, в таком случае, m[1:] бы на самом деле означает m[1:][1:], который будет означать, m[1:][1:][1:] и т.д.

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

  • Нет связанных вопросов^_^