Разве строки Python не являются неизменяемыми? Тогда почему + "" + b работает?

Я понял, что строки Python неизменяемы.

Я попробовал следующий код:

a = "Dog"
b = "eats"
c = "treats"

print a, b, c
# Dog eats treats

print a + " " + b + " " + c
# Dog eats treats

print a
# Dog

a = a + " " + b + " " + c
print a
# Dog eats treats
# !!!

Не должен ли Python помешать назначению? Я, вероятно, что-то пропустил.

Любая идея?

Ответ 1

Первый a указал на строку "Собака". Затем вы изменили переменную a, чтобы указать на новую строку "Собаки ест лечит". Вы на самом деле не мутировали строку "Собака". Строки неизменяемы, переменные могут указывать на то, что они хотят.

Ответ 2

Строковые объекты сами по себе являются неизменными.

Переменная a, которая указывает на строку, изменена.

Рассмотрим:

a = "Foo"
# a now points to "Foo"
b = a
# b points to the same "Foo" that a points to
a = a + a
# a points to the new string "FooFoo", but b still points to the old "Foo"

print a
print b
# Outputs:

# FooFoo
# Foo

# Observe that b hasn't changed, even though a has.

Ответ 3

Переменная a указывает на объект "Собака". Лучше всего думать о переменной в Python как теге. Вы можете переместить тег на разные объекты, что и было, когда вы изменили a = "dog" на a = "dog eats treats".

Однако неизменность относится к объекту, а не к тегу.


Если вы попытались a[1] = 'z' сделать "dog" в "dzg", вы получите ошибку:

TypeError: 'str' object does not support item assignment" 

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

Ответ 4

Что-то можно изменить только тогда, когда мы можем изменить значения, хранящиеся в памяти, без изменения самой ячейки памяти.

Трюк: если вы обнаружите, что расположение памяти до и после изменения одинаково, оно изменено.

Например, список изменен. Как?

>> a = ['hello']
>> id(a)
139767295067632

# Now let modify
#1
>> a[0] = "hello new"
>> a
['hello new']
Now that we have changed "a", let see the location of a
>> id(a)
139767295067632
so it is the same as before. So we mutated a. So list is mutable.

Строка неизменна. Как мы это докажем?

> a = "hello"
> a[0]
'h'
# Now let modify it
> a[0] = 'n'
----------------------------------------------------------------------

получаем

TypeError: объект 'str' не поддерживает назначение элементов

Итак, мы не смогли изменить строку. Это означает, что строка является неизменной.

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

>> a = "hello"
>> id(a)
139767308749440
>> a ="world"
>> id(a)
139767293625808

id до и после переназначения отличается, поэтому это доказывает, что вы на самом деле не мутируете, но указываете переменную на новое местоположение. Что не мутирует эту строку, но мутирует эту переменную.

Ответ 5

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

Ответ 6

Рассмотрим:

>>> a='asdf'
>>> a.__repr__
<method-wrapper '__repr__' of str object at 0x1091aab90>
>>> a='asdf'
>>> a.__repr__
<method-wrapper '__repr__' of str object at 0x1091aab90>
>>> a='qwer'
>>> a.__repr__
<method-wrapper '__repr__' of str object at 0x109198490>

Обратите внимание, что шестнадцатеричное расположение в памяти не изменилось, когда я дважды сохранял одно и то же значение в переменной. Это изменилось, когда я сохранил другое значение. Строка неизменна. Не из-за фанатизма, а потому, что вы платите за производительность создания нового объекта в памяти. Переменная a - это просто метка, указывающая на этот адрес памяти. Это может быть изменено, чтобы указать на что-либо.

Ответ 7

Оператор a = a + " " + b + " " + c может быть разбит на основе указателей.

a + " " говорит мне, что указывает a, который нельзя изменить, и добавьте " " в мой текущий рабочий набор.

память:

working_set = "Dog "
a = "Dog" 
b = "eats"
c = "treats"

+ b говорит мне, что указывает b, который нельзя изменить, и добавьте его в текущий рабочий набор.

память:

working_set = "Dog eats"
a = "Dog" 
b = "eats"
c = "treats"

+ " " + c говорит добавить " " к текущему набору. Затем дайте мне то, что указывает c, которое нельзя изменить, и добавьте его в текущий рабочий набор. память:

working_set = "Dog eats treats"
a = "Dog" 
b = "eats"
c = "treats"

Наконец, a = говорит, что мой указатель указывает на результирующий набор.

память:

a = "Dog eats treats"
b = "eats"
c = "treats"

"Dog" исправляется, потому что больше ссылок не связывает с ним кусок памяти. Мы никогда не изменяли раздел памяти "Dog", в котором подразумевается неизменяемое. Однако мы можем изменить, какие метки, если таковые имеются, указывают на этот раздел памяти.

Ответ 8

l = [1,2,3]
print id(l)
l.append(4)
print id(l) #object l is the same

a = "dog"
print id(a)
a = "cat"
print id(a) #object a is a new object, previous one is deleted

Ответ 9

Существует разница между данными и меткой, с которой она связана. Например, когда вы делаете

a = "dog"

данные "dog" создаются и помещаются под меткой a. Метка может измениться, но то, что в памяти, не будет. Данные "dog" будут по-прежнему существовать в памяти (пока сборщик мусора не удалит его) после того, как вы сделаете

a = "cat"

В вашей программе a теперь ^ указывает на ^ "cat", но строка "dog" не изменилась.

Ответ 10

Строки Python неизменяемы. Однако a не является строкой: это переменная со строковым значением. Вы не можете мутировать строку, но можете изменить какое значение переменной для новой строки.

Ответ 11

Переменные могут указывать на нужное место. Ошибка выдается, если вы выполните следующее:

a = "dog"
print a                   #dog
a[1] = "g"                #ERROR!!!!!! STRINGS ARE IMMUTABLE

Ответ 12

Строковые объекты Python являются неизменяемыми. Пример:

>>> a = 'tanim'
>>> 'Address of a is:{}'.format(id(a))
'Address of a is:64281536'
>>> a = 'ahmed'
>>> 'Address of a is:{}'.format(id(a))
'Address of a is:64281600'

В этом примере мы можем видеть, что когда мы назначаем другое значение в a, оно не изменяется. Новый объект создается.
И это не может быть изменено. Пример:

  >>> a[0] = 'c'
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
    **TypeError**: 'str' object does not support item assignment

Произошла ошибка.

Ответ 13

>>> a = 'dogs'

>>> a.replace('dogs', 'dogs eat treats')

'dogs eat treats'

>>> print a

'dogs'

Неизменяемый, не так ли?!

Часть изменения переменных уже обсуждена.

Ответ 14

Рассмотрим это дополнение к вашему примеру

 a = "Dog"
 b = "eats"
 c = "treats"
 print (a,b,c)
 #Dog eats treats
 d = a + " " + b + " " + c
 print (a)
 #Dog
 print (d)
 #Dog eats treats

Одно из более точных объяснений, которые я нашел в блоге:

В Python (почти) все является объектом. То, что мы обычно называем "переменными" в Python, более правильно называют именами. Аналогично, "присваивание" на самом деле является связыванием имени с объектом. Каждая привязка имеет область видимости, обычно определяющую ее видимость, обычно это блок, в котором происходит имя.

Например:

some_guy = 'Fred'
# ...
some_guy = 'George'

Когда мы позже скажем some_guy = 'George', объект string, содержащий 'Fred', не изменяется. Мы только что изменили привязку имени some_guy. Однако мы не изменили ни строковые объекты "Фред", ни "Джордж". Насколько нам известно, они могут жить бесконечно.

Ссылка на блог: https://jeffknupp.com/blog/2012/11/13/is-python-callbyvalue-or-callbyreference-neither/

Ответ 15

Добавьте немного больше к вышеупомянутым ответам.

id переменной изменяется при переназначении.

>>> a = 'initial_string'
>>> id(a)
139982120425648
>>> a = 'new_string'
>>> id(a)
139982120425776

Это означает, что мы изменили переменную a, чтобы она указала на новую строку. Теперь существует два string (стр.) Объекта:

'initial_string' с id = 139982120425648

и

'new_string' с id = 139982120425776

Рассмотрим приведенный ниже код:

>>> b = 'intitial_string'
>>> id(b)
139982120425648

Теперь b указывает на 'initial_string' и имеет тот же id, что и a до переназначения.

Таким образом, 'intial_string' не был мутирован.

Ответ 16

'mutable' означает, что мы можем изменить содержимое строки, "неизменяемый" означает, что мы не можем добавить дополнительную строку.

click for photo proof

Ответ 17

Резюмируя:

a = 3
b = a
a = 3+2
print b
# 5

Не является неизменным:

a = 'OOP'
b = a
a = 'p'+a
print b
# OOP

Неизменное:

a = [1,2,3]
b = range(len(a))
for i in range(len(a)):
    b[i] = a[i]+1

Это ошибка в Python 3, потому что она неизменна. И не ошибка в Python 2, потому что, очевидно, она не является неизменной.

Ответ 18

Вы можете сделать массив numpy неизменным и использовать первый элемент:

numpyarrayname[0] = "write once"

то

numpyarrayname.setflags(write=False)

или

numpyarrayname.flags.writeable = False

Ответ 19

Встроенная функция id() возвращает идентификатор объекта в виде целого числа. Это целое число обычно соответствует расположению объектов в памяти.

\>>a='dog'
\>>print(id(a))

139831803293008

\>>a=a+'cat'
\>>print(id(a))

139831803293120

Изначально "a" хранится в ячейке памяти 139831803293008, поскольку строковый объект неизменен в python, если вы попытаетесь изменить и переназначить ссылку, она будет удалена и будет указателем на новую ячейку памяти (139831803293120).

Ответ 20

Это изображение дает ответ. Пожалуйста, прочитайте это.

enter image description here