November 2019

S M T W T F S
      12
34 5 678 9
10111213141516
17181920212223
24252627282930

Style Credit

Expand Cut Tags

No cut tags
Sunday, May 31st, 2009 10:54 am

Делай раз:

Делай два:

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

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

Saturday, September 5th, 2009 03:46 pm (UTC)
нет, не называется. пример:

по ссылке:

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
Saturday, September 5th, 2009 05:16 pm (UTC)
а если параметр является списком, то список вполне себе изменяется:

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

b=[]
# b = []

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

из чего следует, что список передаётся по ссылке
Saturday, September 5th, 2009 05:23 pm (UTC)
Но ссылка на него — по значению ;-)
Saturday, September 5th, 2009 05:27 pm (UTC)
а ссылка разве может передаваться ещё как-то?
Saturday, September 5th, 2009 05:30 pm (UTC)
Да. По ссылке же (когда внутри функции "arg = new Obj()" изменит ту переменную, которая подставлялась в вызов функции, если она там была). Или по имени (поиск по имени в контексте уже функции). Или по отложенному вычислению (что в некоторых тонких случая отличается от «по имени»).
Saturday, September 5th, 2009 05:40 pm (UTC)
а, ну это если в языке есть отдельные сущности "объект" и "ссылка" (или хотя бы "указатель"), как в C++, или, там, в перле, тогда да.
а в питоне их отдельно вроде нет.
Saturday, September 5th, 2009 05:28 pm (UTC)
нет, список не передается по ссылке:

def f(l):
l = [1]

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

ссылка на список передается по значению.
Saturday, September 5th, 2009 05:31 pm (UTC)
Список таки передаётся по ссылке а не по копии. Вот ссылка на него — по значению, да. Иначе бы в вашем примере l.push(2) не меняло бы a снаружи.
Saturday, September 5th, 2009 05:43 pm (UTC)
список вообще не передается, передается ссылка :)
Saturday, September 5th, 2009 05:47 pm (UTC)
Это в нормальных языках и называется “передача по ссылке” :)
Saturday, September 5th, 2009 05:52 pm (UTC)
отнюдь. передачей по ссылке обычно называется передача указателя на свою локальную переменную (e.g. ref и out параметры в C#). тут же значение локальной переменной передано по значению (скопировано), просто само значение -- указатель.
Saturday, September 5th, 2009 05:55 pm (UTC)
Нет, само значение — не указатель. Потому что с ним ничего сделать нельзя. С самим значением. Только с тем, на что оно ссылается.
Saturday, September 5th, 2009 06:03 pm (UTC)
еще как можно. можно поменять его на другой указатель. те же примеры, переписанные на С++:

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)
Saturday, September 5th, 2009 06:13 pm (UTC)
еще как можно. можно поменять его на другой указатель.
Ну да. И всё. Разыменовать нельзя (что бы bit-to-bit Скопировать объект), арифметика адресная не работает…

В общем, я же говорю — это терминологический спор. Для меня это передача ОБЪЕКТА по ссылке потому что УКАЗАТЕЛЬ в питоне собственной ценности не имеет вовсе, а передача ОБЪЕКТА по значению невозможна вовсе.
Saturday, September 5th, 2009 06:49 pm (UTC)
разыменование автоматическое, скопировать можно (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 результатов в список

разница, конечно, очень тонкая, но важная.
Saturday, September 5th, 2009 06:54 pm (UTC)
разыменование автоматическое
Как у ссылки (то, что можно переприсвоить — НЕ как у ссылки)

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

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

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

Ещё раз: ОБЪЕКТЫ передаются в питоне ПО ССЫЛКЕ. ССЫЛКА — по значеню, да.
Saturday, September 5th, 2009 07:16 pm (UTC)
ну, в С++ тоже при копировании разыменованием указателя будет вызван operator= определенный в классе. memcpy фактически может скопировать объект, но формат не POD-объекта не определен.

да вообще call by -- ущербная терминология. правильнее сказать, что в питоне reference semantics, так имхо понятнее. но ссылки тоже можно передавать по ссылке, см. ref/out в C# :-)
Saturday, September 5th, 2009 07:17 pm (UTC)
но ссылки тоже можно передавать по ссылке, см. ref/out в C# :-)
Да-да, я ка краз хотел сказать что если res_type2 — объектный, то мы получим двойную ссылку по сути :)
Saturday, September 5th, 2009 06:57 pm (UTC)
В википедии вон вообще считают, что то, что в питоне — Call by sharing :)
Saturday, September 5th, 2009 06:58 pm (UTC)
И вот ровно то, о чём я тут толкую:

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.
Saturday, September 5th, 2009 05:48 pm (UTC)
ну тогда вопрос в том, передаётся ли ссылка на оригинал фактического параметра или на его копию
Saturday, September 5th, 2009 05:53 pm (UTC)
на оригинал, конечно.
Saturday, September 5th, 2009 06:30 pm (UTC)
тогда это таки передача по ссылке.
я, кажется, понял. формальный параметр изначально показывает на тот же объект, что и фактический, но в отличие от других языков, его можно переназначить на другой объект. в частности, прямым присваиванием.
Saturday, September 5th, 2009 06:42 pm (UTC)
Ну, с указателями в C/C++ та же фигня :)
Saturday, September 5th, 2009 05:36 pm (UTC)
а почему в моём примере append внутри функции подействовал на внешний список??
Saturday, September 5th, 2009 05:37 pm (UTC)
http://effbot.org/zone/python-objects.htm
так понятнее?
Tuesday, October 6th, 2009 07:21 am (UTC)
дочитал до 9 главы, всё устаканилось. просто в питоне пространства имён принципиально отделены от самих объектов. а передача таки по ссылке, других вариантов в питоне как бы и нет
Saturday, September 5th, 2009 05:32 pm (UTC)
а вообще я чего-то не понял. получается, что скалярная переменная передается по значению, а список - по ссылке. где же единообразие?
Saturday, September 5th, 2009 07:00 pm (UTC)
Все передается однообразно. Просто большинство типов данных в питоне немутабельно.
In [1]: a = 1

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

In [3]: a += 3

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