Забавно иногда открывать для себя лаконичные способы делать что-то в синтаксисе нового языка. Сегодня возникла нужда поменять значения двух переменных, и я подумал, что традиционный способ:
temp = x
x = y
y = temp
... слишком длинен. Не может быть, чтобы в Питоне не было чего-нибудь покороче.
В Питоне есть тип данных, который называется "tuple" (и который в руском языке должен называться "кортеж" — слово, возможно знакомое тем, кто изучал в институте высшую математику и что-то помнит из тех времен). По сути он представляет собой пачку любых значений в определенном порядке, с которой можно работать, как с единым целым, например в функцию передать:
x = (1, 'abc', 3) # tuple
some_func(x)
С этими кортежами связана интересная особенность оператора присваивания. Он может автоматически распаковывать и запаковывать несколько значений в кортежи и обратно:
x, y, z = (1, 2, 3) # x = 1, y = 2, z = 3
t = 1, 2, 3 # t = (1, 2, 3)
Вот это мне и приглянулось для обмена значениями. Выглядит, по-моему, просто чудесно:
x, y = y, x
Комментарии: 20
Насколько я помню, в перле всегда была такая возможность :-)
($x, $y) = ($y, $x);
Очень часто еще используют аналогичные схемы для заполнения набора переменных значениями из кусочков строки:
($x, $y, $x) = split /какой-нить разделитель/;
а как насчет массивов? :)
в перле очень похож обме на листы:
($x, $y) = ($y, $x);
Осталось еще, чтобы ПХПшники прибежали и начали свои варианты предлагать :-)
А потом можно будет организовать проект по поиску самых красивых/лаконичных/етс методов обмена значениями переменных.
Я буду за ПХПшника :-)
list($a, $b) = array($b, $a);
Кстати, насчёт ПХПшников. Я показал своим коллегам эту возможность и они тут же ответили мне:
list($b, $a) = array($a, $b);
Это просто ужасно! =)
Кстати, вот приём на Python'e, до которого я сам дошёл. cursor.fetchall() возвращает словарь. В моём случае он выглядел так:
{"ref_link": "www.somesite.com", "ref_link": "www.ya.ru", "ref_link": "www.rambler.ru"}
нужно было получить список ["www.somesite.com", "www.ya.ru", "www.rambler.ru"]
вот строчка из программы:
return [link["ref_link"] for link in cur.fetchall()]
2MkDir
я вот как-то очень сильно не понимаю, как в питоне можно создать словарь c несколькими значениями под одним ключом.
>>> a = {"ref_link": "www.somesite.com", "ref_link": "www.ya.ru", "ref_link": "www.rambler.ru"}; >>> a {'ref_link': 'www.rambler.ru'} >>>
можно это как-то разъяснить?
кроме того
for link in {.....}
будет перебирать ключи словаря. ключ словаря в данном случае - строка. потом с этой строкой сделать сделать link["ref_link"] - никак нельзя, потому как "string indices must be integers".....Есть универсальный для всех языков метод через xor :)
a ^= b
b ^= a
a ^= b
Описание:
http://wikisource.org/wiki/XOR_swap_algorithm
fetchall() всегда возвращает список (точнее кортеж). В зависимости от настройки это либо список словарей, либо список списков.
Т.е. не
{”ref_link”: “www.somesite.com”, “ref_link”: “www.ya.ru”, “ref_link”: “www.rambler.ru”}
а
({”ref_link”: “www.somesite.com”}, { “ref_link”: “www.ya.ru”}, { “ref_link”: “www.rambler.ru”})
Причем это поведение не по умолчанию, а по умолчанию fetchall() возвращает список списка:
(( “www.somesite.com”, ), ( “ref_link”: “www.ya.ru”, ), ( “ref_link”: “www.rambler.ru”, ))
2Merle
А для строк? или вообще для нецелочисленных ;)
2наблюдатель
Не вижу проблемы. Строка - такая же последовательность 0 и 1, которую также можно несколько раз xor.
А можем и предложить. И покрасивее!
Прошу заметить, что ничего не надо "автоматически распаковывать и запаковывать".
2Merle
Это не меняет сути - метод универсален только для целочисленных типов. Возьмите float'ы, object'ы или язык/тип, где строка является последовательностью символов, а не байтов. Метод работать не будет (а ведь именно универсальность Вы подчеркивали).
2наблюдатель
Вы очень серьезно восприняли мою шутку об универсальности.
:) данный метод я привел скорее в качестве забавного и универсального на низком уровне примера.
понятно, что с его помощью можно реализовать и посимвольный обмен строк. Криво, но можно.
Но в общем-то использование этого метода в 99% задач неоправдано. В той же статье на Википедии на которую я давал ссылку написано что "However on modern (desktop) CPUs, the XOR technique is considerably slower than using a temporary variable to do swapping."
Красиво, но не умеет строки :-)
Предлагаю альтернативу:
$a = @$b . (($b = a) &&