dil: (Default)
dil ([personal profile] dil) wrote2009-05-31 10:54 am

Грабельки, грабельки…

Делай раз:

Делай два:

Я догадывался, что Германия – это не город. Но если уж вы сами туда кроме городов иногда подставляете страны, так, наверное, и проверять в списке стран тоже надо?

Оригинал этой записи в личном блоге.

[identity profile] blacklion.livejournal.com 2009-09-05 03:18 pm (UTC)(link)
Это терминологический спор. Как и by-ref И by-pointer — одно и то же или нет :)

[identity profile] dil.livejournal.com 2009-09-05 05:18 pm (UTC)(link)
не понял. by ref и by value - это принципиально разные вещи, тут никакого терминологического спора нет.
если в функцию передаётся копия фактического параметра, и изменение его внутри функции не приводит к изменению самого фактического параметра - это передача по значению, если передаётся ссылка на фактический параметр и его можно изменить внутри функции - это передача по ссылке.

[identity profile] blacklion.livejournal.com 2009-09-05 05:23 pm (UTC)(link)
не понял. by ref и by value - это принципиально разные вещи, тут никакого терминологического спора нет.
Ok, если объекты иммутабельны — то есть разница или нет? А если нет копий?

[identity profile] dil.livejournal.com 2009-09-05 05:26 pm (UTC)(link)
если они неизменяемые, то разница исключительно в эффективности, для прикладного программиста они будут выглядеть одинаково.
вопрос, конечно, о том случае, когда объект изменяемый

[identity profile] dil.livejournal.com 2009-09-06 12:46 pm (UTC)(link)
а чего тут спорить? для языков, в которых указатель и ссылка - разные вещи, как в C++, - это разные понятия. а где указателей нет в принципе, как в джаве, - одно и то же. но лично я предпочитаю и там использовать понятие "ссылка" аналогично C++.

[identity profile] duke-igthorn.livejournal.com 2009-09-06 02:03 pm (UTC)(link)
В жабке есть понятие переменной и объекта. Переменная все-таки передается по значению.

[identity profile] dil.livejournal.com 2009-09-06 02:22 pm (UTC)(link)
ну и на здоровье. мы же говорим о reference vs pointer, а не reference vs value

[identity profile] duke-igthorn.livejournal.com 2009-09-06 02:29 pm (UTC)(link)
я думал, мы by ref vs by val?
ext_659502: (Default)

[identity profile] some41.livejournal.com 2009-09-05 03:46 pm (UTC)(link)
нет, не называется. пример:

по ссылке:

f(int& x) { x = 5 };

a = 1;
f(a);
// a == 5

в питоне (refs by value)

def f(x):
x = 5

a = 1
f(a)
// a == 1

[identity profile] dil.livejournal.com 2009-09-05 05:16 pm (UTC)(link)
а если параметр является списком, то список вполне себе изменяется:

def f(x,a):
a.append(x)

b=[]
# b = []

f('foo',b)
# b = ['foo']

из чего следует, что список передаётся по ссылке

[identity profile] blacklion.livejournal.com 2009-09-05 05:23 pm (UTC)(link)
Но ссылка на него — по значению ;-)

[identity profile] dil.livejournal.com 2009-09-05 05:27 pm (UTC)(link)
а ссылка разве может передаваться ещё как-то?

[identity profile] blacklion.livejournal.com 2009-09-05 05:30 pm (UTC)(link)
Да. По ссылке же (когда внутри функции "arg = new Obj()" изменит ту переменную, которая подставлялась в вызов функции, если она там была). Или по имени (поиск по имени в контексте уже функции). Или по отложенному вычислению (что в некоторых тонких случая отличается от «по имени»).

[identity profile] dil.livejournal.com 2009-09-05 05:40 pm (UTC)(link)
а, ну это если в языке есть отдельные сущности "объект" и "ссылка" (или хотя бы "указатель"), как в C++, или, там, в перле, тогда да.
а в питоне их отдельно вроде нет.
ext_659502: (Default)

[identity profile] some41.livejournal.com 2009-09-05 05:28 pm (UTC)(link)
нет, список не передается по ссылке:

def f(l):
l = [1]

a = []
f(a)
// a == []

ссылка на список передается по значению.

[identity profile] blacklion.livejournal.com 2009-09-05 05:31 pm (UTC)(link)
Список таки передаётся по ссылке а не по копии. Вот ссылка на него — по значению, да. Иначе бы в вашем примере l.push(2) не меняло бы a снаружи.
ext_659502: (Default)

[identity profile] some41.livejournal.com 2009-09-05 05:43 pm (UTC)(link)
список вообще не передается, передается ссылка :)

[identity profile] blacklion.livejournal.com 2009-09-05 05:47 pm (UTC)(link)
Это в нормальных языках и называется “передача по ссылке” :)
ext_659502: (Default)

[identity profile] some41.livejournal.com 2009-09-05 05:52 pm (UTC)(link)
отнюдь. передачей по ссылке обычно называется передача указателя на свою локальную переменную (e.g. ref и out параметры в C#). тут же значение локальной переменной передано по значению (скопировано), просто само значение -- указатель.

[identity profile] blacklion.livejournal.com 2009-09-05 05:55 pm (UTC)(link)
Нет, само значение — не указатель. Потому что с ним ничего сделать нельзя. С самим значением. Только с тем, на что оно ссылается.
ext_659502: (Default)

[identity profile] some41.livejournal.com 2009-09-05 06:03 pm (UTC)(link)
еще как можно. можно поменять его на другой указатель. те же примеры, переписанные на С++:

f(int* x) { x = new int(5); }

a = new int(1);
f(a);
// *a == int(1)

f(list* l) { l = new list(new int(1)); } // заменяем указатель, значение не меняется

a = new list();
f(a);
// *a == list()

f(list* l) { l->append(new int(1)); } // используем указатель, чтобы поменять значение

a = new list();
f(a);
// *a == list(1)

[identity profile] blacklion.livejournal.com 2009-09-05 06:13 pm (UTC)(link)
еще как можно. можно поменять его на другой указатель.
Ну да. И всё. Разыменовать нельзя (что бы bit-to-bit Скопировать объект), арифметика адресная не работает…

В общем, я же говорю — это терминологический спор. Для меня это передача ОБЪЕКТА по ссылке потому что УКАЗАТЕЛЬ в питоне собственной ценности не имеет вовсе, а передача ОБЪЕКТА по значению невозможна вовсе.
ext_659502: (Default)

[identity profile] some41.livejournal.com 2009-09-05 06:49 pm (UTC)(link)
разыменование автоматическое, скопировать можно (import copy), адресная арифметика для указателя на один объект и в С запрещена (по факту обычно работает, но стандарт говорит undefined behaviour). да и вообще, почему над указателем должны работать операции из С?

назвать можно хоть горшком, факт в том, что в питоне нельзя поменять binding внешней переменной, что является одним из основных назначений call by ref в некоторых языках. т.е. если из функции нужно вернуть несколько значений, с call by ref это делается так:

function foo(arg: type, OUT res2: res2_type): res1_type;

(или res1_type foo(type arg, out res2_type res2);)

res1 = foo(x, res2); // в res2 попадает второй результат

в питоне _так_ сделать нельзя. можно сделать похоже:

additional_results = []
res = foo(x, additional_results) // foo делала append результатов в список

разница, конечно, очень тонкая, но важная.

[identity profile] blacklion.livejournal.com 2009-09-05 06:54 pm (UTC)(link)
разыменование автоматическое
Как у ссылки (то, что можно переприсвоить — НЕ как у ссылки)

скопировать можно (import copy)
Это клонирование ведь будет, не тупое копирование? Или нет?

да и вообще, почему над указателем должны работать операции из С?
Ну, потому что УКАЗАТЕЛЬ — это по определению адрес в памяти :) А во всяких C#, Python, PErk, JAva & Ko нет УКАЗАТЕЛЕЙ а есть ССЫЛКИ. Которые можно обычно переприсваивать (в отличие от ссылок в C++).

назвать можно хоть горшком, факт в том, что в питоне нельзя поменять binding внешней переменной, что является одним из основных назначений call by ref в некоторых языках
Вообще, я же говорю — тут путаница и каша. Да в той же википедии почитать — они путают в одном текстк call by ref и что-то ещё (читал пару месяцев назад этот бред, уже не помню).

Ещё раз: ОБЪЕКТЫ передаются в питоне ПО ССЫЛКЕ. ССЫЛКА — по значеню, да.
ext_659502: (Default)

[identity profile] some41.livejournal.com 2009-09-05 07:16 pm (UTC)(link)
ну, в С++ тоже при копировании разыменованием указателя будет вызван operator= определенный в классе. memcpy фактически может скопировать объект, но формат не POD-объекта не определен.

да вообще call by -- ущербная терминология. правильнее сказать, что в питоне reference semantics, так имхо понятнее. но ссылки тоже можно передавать по ссылке, см. ref/out в C# :-)

[identity profile] blacklion.livejournal.com 2009-09-05 07:17 pm (UTC)(link)
но ссылки тоже можно передавать по ссылке, см. ref/out в C# :-)
Да-да, я ка краз хотел сказать что если res_type2 — объектный, то мы получим двойную ссылку по сути :)

[identity profile] blacklion.livejournal.com 2009-09-05 06:57 pm (UTC)(link)
В википедии вон вообще считают, что то, что в питоне — Call by sharing :)

[identity profile] blacklion.livejournal.com 2009-09-05 06:58 pm (UTC)(link)
И вот ровно то, о чём я тут толкую:

However, the term "call by sharing" is not in common use; the terminology is inconsistent across different sources. For example, in the Java community, they say that Java is pass-by-value, whereas in the Ruby community, they say that Ruby is pass-by-reference, even though the two languages exhibit the same semantics.

[identity profile] dil.livejournal.com 2009-09-05 05:48 pm (UTC)(link)
ну тогда вопрос в том, передаётся ли ссылка на оригинал фактического параметра или на его копию
ext_659502: (Default)

[identity profile] some41.livejournal.com 2009-09-05 05:53 pm (UTC)(link)
на оригинал, конечно.

[identity profile] dil.livejournal.com 2009-09-05 06:30 pm (UTC)(link)
тогда это таки передача по ссылке.
я, кажется, понял. формальный параметр изначально показывает на тот же объект, что и фактический, но в отличие от других языков, его можно переназначить на другой объект. в частности, прямым присваиванием.

[identity profile] blacklion.livejournal.com 2009-09-05 06:42 pm (UTC)(link)
Ну, с указателями в C/C++ та же фигня :)

[identity profile] dil.livejournal.com 2009-09-05 05:36 pm (UTC)(link)
а почему в моём примере append внутри функции подействовал на внешний список??
ext_659502: (Default)

[identity profile] some41.livejournal.com 2009-09-05 05:37 pm (UTC)(link)
http://effbot.org/zone/python-objects.htm
так понятнее?

[identity profile] dil.livejournal.com 2009-10-06 07:21 am (UTC)(link)
дочитал до 9 главы, всё устаканилось. просто в питоне пространства имён принципиально отделены от самих объектов. а передача таки по ссылке, других вариантов в питоне как бы и нет

[identity profile] dil.livejournal.com 2009-09-05 05:32 pm (UTC)(link)
а вообще я чего-то не понял. получается, что скалярная переменная передается по значению, а список - по ссылке. где же единообразие?

[identity profile] shigin.livejournal.com 2009-09-05 07:00 pm (UTC)(link)
Все передается однообразно. Просто большинство типов данных в питоне немутабельно.
In [1]: a = 1

In [2]: id(a)
Out[2]: 12678648

In [3]: a += 3

In [4]: id(a)
Out[4]: 12678576