Какие из них неизменяемы в Python?

#python #immutability

#python #неизменяемость

Вопрос:

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

Ниже приведены объекты e, f, g, i

 class e: pass
f = e()
g = pi # (g's "type" in Sage is symbolic expression. It's supposed to be 3.1415....etc)
i = lambda x: x*x
  

Я понимаю, что e — это класс, что означает, что он изменяемый (имеет ли смысл неизменяемый класс? Разве нельзя изменить все классы?). Поскольку f является экземпляром класса, я предполагаю, что он также изменяем, поскольку классы изменяемы.

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

Наконец, i — это функция, которая означает, что она должна быть изменяемой?

Я не совсем уверен, что понимаю концепцию неизменяемости. Что бы это значило, чтобы функция была неизменяемой? Чтобы класс был неизменяемым?

Ответ №1:

e является изменяемым. Вы можете, например, добавить новый метод в класс: e.foo = lambda self,x: x .

f является изменяемым. Вы можете, например, добавить новое поле к этому экземпляру класса: f.x = 99 .

g является неизменяемым. Вы ничего не можете изменить в этом.

i не является неизменяемым. Вы можете делать с ним всевозможные ужасные вещи: i.func_code = (lambda x: 123).func_code после чего i(10) будет 123 вместо 100. (Вы также можете сделать с этим более разумные вещи. После i.__doc__ = "This function returns the square of its argument." вы получите более полезный результат от help(i) .)

Объект является изменяемым, если с объектом можно что-то сделать, что изменит его возможное будущее поведение. Вы не можете изменить поведение 10 ; вы можете изменить поведение объекта функции, или класса, или экземпляра класса, или списка. (Но не кортеж. Как только кортеж создан, он остается таким, какой он есть, до тех пор, пока он существует.)

Комментарии:

1. Комментарий о кортежах действительно верен только тогда, когда все, на что ссылается кортеж, также неизменяемо.

2. Хммм, вроде того. Изменение чего-либо другого, на что ссылается кортеж, на самом деле ничего не делает с кортежем . Но я понимаю вашу точку зрения.

3. Интересно, что определение в документах соответствует вашему объяснению (т. Е. кортежи официально считаются неизменяемыми, хотя их значение может меняться со временем): docs.python.org/reference/datamodel.html

4. Если бы я собирался быть полностью компьютерным специалистом по этому поводу, я бы предположил, что нам действительно нужны два понятия неизменяемости — назовите их «локально неизменяемыми» и «транзитивно неизменяемыми» или что-то в этом роде — где первое означает «ничто из того, что вы делаете непосредственно с объектом, не изменяет его поведение», а второе эквивалентно обоим (1) «объект локально неизменяем, и поэтому из него все достижимо» и (2) «ничто из того, что вы делаете с использованием объекта, не изменяет его поведение».

5. Да, перечитывание определений в документах Python напомнило мне, насколько сложно может быть провести четкую границу между ними, как только вы начнете рассматривать угловые случаи «это зависит от того, что вы подразумеваете под неизменяемостью».

Ответ №2:

Формально? Объект является изменяемым, если он может изменять значение без изменения идентификатора.

Списки изменяемы, поэтому значение конкретного экземпляра может меняться со временем:

 >>> x = orig_x = []
>>> x == []
True
>>> x  = [1]
>>> x == []      # The value of x has changed
False
>>> x is orig_x  # But the identity remains the same
True
  

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

 >>> x = orig_x = 1
>>> x == 1
True
>>> x  = 1
>>> x == 1        # Again, the value of x has changed
False
>>> x is orig_x   # But now the identity has changed as well
False
  

Неизменяемость — важная концепция, поскольку знание того, что значение объекта не может измениться, позволяет вам делать определенные предположения относительно него (например, dict эффективно требуются неизменяемые ключи и set и frozenset требуют неизменяемых членов, поскольку значение объекта влияет на то, как оно должно храниться в структуре данных. Если были разрешены изменяемые записи, они могут оказаться в неправильном месте, если их изменить после сохранения)

Вопреки распространенному мнению, пользовательские классы, которые не переопределяют определение равенства, технически неизменяемы. Это потому, что определение «значения» пользовательского класса по умолчанию является просто id(self) . Когда значение объекта является его идентификатором, очевидно, что они не могут отличаться с течением времени, и, следовательно, объект не является «изменяемым».

Неофициально? Большинство людей используют интуитивно понятное определение «Могу ли я это изменить?» в соответствии с ответом Гарета Маккохана. Это та же основная идея, что и формальное определение, просто используется более широкое значение термина «значение», чем техническое определение, в терминах проверок на равенство.

Комментарии:

1. Строго говоря, dict / set / frozenset только обеспечивает выполнение требования, чтобы объект был хэшируемым, а не полностью неизменяемым. Однако вы можете столкнуться с очень странным поведением, если ваши ключи / элементы на самом деле не являются неизменяемыми.

2. Также смотрите Введение в: docs.python.org/reference/datamodel.html . Как указано во введении, граница между изменяемым и неизменяемым иногда может быть немного размытой.