Питон и мутация

User avatar
perasperaadastra
Уже с Приветом
Posts: 20128
Joined: 21 Feb 2009 22:55
Location: Лох Онтарио

Питон и мутация

Post by perasperaadastra »

В питоне меня напрягает мутация списков

Вот пример:

Code: Select all

>>> a = [1, 2, 3]
>>> b = a
>>> b.append(4)
>>> a
[1, 2, 3, 4]
>>> b
[1, 2, 3, 4]
>>>
То же самое получается если использовать b += [4]
Однако, если писать b = b + [4], то переменная переназначается.

Зачем в питоне такая логика? Почему нельзя переназначать переменные по умолчанию, а если хочется поменять оригинал, то использовать указатели? В чем преимущество модели данных питона?
Palych
Уже с Приветом
Posts: 13682
Joined: 16 Jan 2001 10:01

Re: Питон и мутация

Post by Palych »

perasperaadastra wrote: Почему нельзя переназначать переменные по умолчанию, а если хочется поменять оригинал, то использовать указатели? В чем преимущество модели данных питона?
В инженерии любое решение суть компромисс: из двух зол выбирают меньшее, а из двух благ - большее.
User avatar
perasperaadastra
Уже с Приветом
Posts: 20128
Joined: 21 Feb 2009 22:55
Location: Лох Онтарио

Re: Питон и мутация

Post by perasperaadastra »

Ну вот в данном случае, в чем заключается благо? Я почитал интернеты на эту тему, но там только общие слова...
blanko27
Уже с Приветом
Posts: 2264
Joined: 17 Jun 2003 04:41
Location: Just like US

Re: Питон и мутация

Post by blanko27 »

perasperaadastra wrote:Ну вот в данном случае, в чем заключается благо? Я почитал интернеты на эту тему, но там только общие слова...
У вас b и a (подобно поинтерам в языке C), указывают на тот же объект. Если вы посмотрите адрес в памяти у a и b будут совпадать (hex(id(a)) == hex(id(b))). Операцией "b = b + [4]" вы переназначаете b на новый адрес (hex(id(b + [4]))).
В данном сценарии благо заключается в оптимизации операций с памятью: если оба поинтера указывают на тот же объект вам не надо иметь его вторую копию.
...а мы такой компанией, возьмем, да и припремся к Элис!
User avatar
perasperaadastra
Уже с Приветом
Posts: 20128
Joined: 21 Feb 2009 22:55
Location: Лох Онтарио

Re: Питон и мутация

Post by perasperaadastra »

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

PS Кстати, раз уж пошла речь о С, хочу спросить, можно ли там сделать так, чтобы обычные переменные a и b указывали на один и тот же адрес памяти? Я понимаю, что там можно b сделать указателем, но это будет не адрес объекта, а адрес адреса оригинального объекта:
int a = 10;
int *b;
b = &a;

Можно ли сделать следующим образом, и получится ли как в питоне?:
int a = 10;
int b = *(&a);
OtherSide
Уже с Приветом
Posts: 15770
Joined: 01 Mar 2008 15:14

Re: Питон и мутация

Post by OtherSide »

Все более чем логично. я вообще не знаю питон, но именно такого поведения я бы ожидал.
a += [4] - явное указание на операцию над переменной [a]/ Куда еще нужно сохранить результат как не в нее же
a = a + [4] - конкатенация двух массивов в третий. Результат пишем, куда скажем, хоть в а, хоть в b

То что для переменных другого типа и значения результат идентичный не должно вводить в заблуждение, т.к. функционал операторов разный по определению (иначе бы их не было 2, обошлись бы одним)
User avatar
perasperaadastra
Уже с Приветом
Posts: 20128
Joined: 21 Feb 2009 22:55
Location: Лох Онтарио

Re: Питон и мутация

Post by perasperaadastra »

Но это переменная а в обоих случаях. Только в одном случае она идентична b (содержит тот же адрес), а в другом преназначается и становится уникальной. Причем, это только с мутирующими видами данных типа списков, а с какими-нибудь целыми числами, переназначение происходит всегда.
b += 1 тоже самое, что b = b + 1

Как с этим обстоят дела в других языках? В Джаве, например? Можно ли там мутировать оригинал без использования указателей или как это там называется...?
User avatar
perasperaadastra
Уже с Приветом
Posts: 20128
Joined: 21 Feb 2009 22:55
Location: Лох Онтарио

Re: Питон и мутация

Post by perasperaadastra »

perasperaadastra wrote:PS Кстати, раз уж пошла речь о С, хочу спросить, можно ли там сделать так, чтобы обычные переменные a и b указывали на один и тот же адрес памяти? Я понимаю, что там можно b сделать указателем, но это будет не адрес объекта, а адрес адреса оригинального объекта:
int a = 10;
int *b;
b = &a;

Можно ли сделать следующим образом, и получится ли как в питоне?:
int a = 10;
int b = *(&a);
Напишу чуть формальнее. Можно ли в С сделать так, чтобы &a == &b было истинно?
Варианты:
int b = *(&a)
int &b = &a
User avatar
Flash-04
Уже с Приветом
Posts: 63430
Joined: 03 Nov 2004 05:31
Location: RU -> Toronto, ON

Re: Питон и мутация

Post by Flash-04 »

я конечно уже давно не пишу на C/C++, но что-то мне кажется что нет. & - адрес. Равенство адресов = тождественность переменных, а вроде так нельзя сделать. То есть можно чтобы были переменные указатели ссылающиеся на один адрес, но чтобы две переменные в одном scope - никак. Это только для параметров по ссылке может выполняться, а это разный scope.
Not everyone believes what I believe but my beliefs do not require them to.
User avatar
Relict17
Уже с Приветом
Posts: 573
Joined: 15 Jan 2016 02:50

Re: Питон и мутация

Post by Relict17 »

Можно и в С.

Code: Select all

union u{
 int x;
 int y;
};
union u a;
int main(){
    printf("%p %p\n",&a.x, &a.y);
    return 0;
 }
User avatar
ALV00
Уже с Приветом
Posts: 1494
Joined: 08 Mar 2002 10:01
Location: NJ

Re: Питон и мутация

Post by ALV00 »

perasperaadastra wrote: Как с этим обстоят дела в других языках? В Джаве, например? Можно ли там мутировать оригинал без использования указателей или как это там называется...?
В джаве все переменные, кроме примитивов, ссылочные, включая массивы и коллекшнз. Референсинг и дереференсинг происходит автоматически, специального синтаксиса для этого нет.

List a = new ArrayList();
List b = a;

a и b будут указывать на одну и ту же структуру, мутировать можно через обе переменные.

с примитивами:
int a = 5;
int b = a;

будут два разных значения
blanko27
Уже с Приветом
Posts: 2264
Joined: 17 Jun 2003 04:41
Location: Just like US

Re: Питон и мутация

Post by blanko27 »

perasperaadastra wrote:Напишу чуть формальнее. Можно ли в С сделать так, чтобы &a == &b было истинно?
Сделать-то можно, но оно вам не понравится :)

Code: Select all

#define b a
...а мы такой компанией, возьмем, да и припремся к Элис!
User avatar
perasperaadastra
Уже с Приветом
Posts: 20128
Joined: 21 Feb 2009 22:55
Location: Лох Онтарио

Re: Питон и мутация

Post by perasperaadastra »

ALV00 wrote:В джаве все переменные, кроме примитивов, ссылочные, включая массивы и коллекшнз. Референсинг и дереференсинг происходит автоматически, специального синтаксиса для этого нет.

List a = new ArrayList();
List b = a;

a и b будут указывать на одну и ту же структуру, мутировать можно через обе переменные.

с примитивами:
int a = 5;
int b = a;

будут два разных значения
Тогда это очень похоже на Питон, кроме численных типов:
a = 5
b = a
дает одинаковый адрес для a и b, но мутировать один через другой нельзя в отличие от списков и словарей. Вот это меня и напрягает, потому что нужно помнить, что вот это мутируемый тип, а вот то — нет. :?
User avatar
Flash-04
Уже с Приветом
Posts: 63430
Joined: 03 Nov 2004 05:31
Location: RU -> Toronto, ON

Re: Питон и мутация

Post by Flash-04 »

Relict17 wrote:Можно и в С.
union - это очень особый случай, его нельзя трактовать как независимые переменные. Он для того и создавался чтобы один кусок памяти можно было транслировать в разные типы автоматически.
Not everyone believes what I believe but my beliefs do not require them to.
User avatar
ALV00
Уже с Приветом
Posts: 1494
Joined: 08 Mar 2002 10:01
Location: NJ

Re: Питон и мутация

Post by ALV00 »

perasperaadastra wrote:Вот это меня и напрягает, потому что нужно помнить, что вот это мутируемый тип, а вот то — нет. :?
Вообще то сейчас считается кошерным делать immutable все что только возможно, но для больших структур это слишком дорого. Поэтому идут на компромиссы.
User avatar
oleg lebedev
Уже с Приветом
Posts: 1879
Joined: 03 Dec 2003 23:13
Location: Одесса - Новая Англия

Re: Питон и мутация

Post by oleg lebedev »

perasperaadastra wrote:В питоне меня напрягает мутация списков

Вот пример:

Code: Select all

>>> a = [1, 2, 3]
>>> b = a
>>> b.append(4)
>>> a
[1, 2, 3, 4]
>>> b
[1, 2, 3, 4]
>>>
То же самое получается если использовать b += [4]
Однако, если писать b = b + [4], то переменная переназначается.

Зачем в питоне такая логика? Почему нельзя переназначать переменные по умолчанию, а если хочется поменять оригинал, то использовать указатели? В чем преимущество модели данных питона?
Это, по-моему это совершенно стандартное поведение. В Пёрле - то же самое.
Разве это не shallow copy vs deep copy?
User avatar
Relict17
Уже с Приветом
Posts: 573
Joined: 15 Jan 2016 02:50

Re: Питон и мутация

Post by Relict17 »

Flash-04 wrote:
Relict17 wrote:Можно и в С.
union - это очень особый случай, его нельзя трактовать как независимые переменные. Он для того и создавался чтобы один кусок памяти можно было транслировать в разные типы автоматически.
Вопрос был простой:
Можно ли в С сделать так, чтобы &a == &b было истинно?
Пусть и "особый случай", но работает же. :)

Кстати, в С++ все еще проще.

Code: Select all

int main()
{
	int x = 1;
	int &y = x;
	
	printf("%p %p\n", &x, &y);
	
	return 0;
}
User avatar
Flash-04
Уже с Приветом
Posts: 63430
Joined: 03 Nov 2004 05:31
Location: RU -> Toronto, ON

Re: Питон и мутация

Post by Flash-04 »

ну так конечно! :D
Not everyone believes what I believe but my beliefs do not require them to.
User avatar
perasperaadastra
Уже с Приветом
Posts: 20128
Joined: 21 Feb 2009 22:55
Location: Лох Онтарио

Re: Питон и мутация

Post by perasperaadastra »

Relict17 wrote:

Code: Select all

	int x = 1;
	int &y = x;
Интересно! Жаль, я не знаю, как работают референсы в ЦПП.

Return to “Вопросы и новости IT”