Массив с конца: ~n

Чудесное нашлось в комментариях на «Хабре»: логичный, на мой взгляд, способ получать значения с конца массива. Способ, вообще говоря, для «Пайтона», но и для «ПХП» можно применить.

В «Пайтоне» есть такая проблема, даже не то чтобы проблема, скорее мелкое неудобство, что списки, если их считать с начала, нумеруются с нуля, а если с конца — с минус единицы:

>>> print([1,2,3][0], [3,2,1][-1])
(1, 1)

Лично я к этому так привык, что в нелогичность такого поведения сразу и не вник. Неудобство становится более очевидным, если от фиксированных значений перейти к переменным:

>>> i=2
>>> print([1,2,3,4][i], [4,3,2,1][-i-1])
(3, 3)

Чтобы брать значения с конца, везде, как приклееную, приходится таскать эту дурацкую минус единицу. Но есть способ лучше, более того, я им иногда пользовался, но почему-то не возвёл в систему — можно использовать тильду. Всё сразу становится более логичным:

>>> i=2
>>> print([1,2,3,4][i], [4,3,2,1][~i])
(3, 3)
>>> print([1,2,3][0], [3,2,1][~0])
(1, 1)

Для тех, кто не понимает смысла операции «тильда» можно объяснить, что без тильды значения берутся с начала, с тильдой — с конца. Здо́рово!

Обычно в таких случаях возражают, что новички будут путаться. Это какой-то странный аргумент, честное слово, в «Пайтоне» для новичков очень много новых «значков» — те же декораторы, а «тильда» есть в большинстве распространённых языков, пусть новички учатся, к тому же забыть вычесть единицу — одна из частых ошибок, встречается не только у новичков, но и у матёрых программистов.

Поделиться
Отправить
18 комментариев
zg (zg.livejournal.com)

справедливо для платформ, на которых отрицательные числа представлены в дополнительном коде.

Евгений Степанищев (bolknote.ru)

Комментарий для zg.livejournal.com:

Я, кстати, других платформ и не видел, они бывают?

В любом случае, «Пайтону» до низкого уровня дела нет. Тильда там реализует оператор «NOT», который по определению обязан работать как NOT(n)=-n-1, вот и документация «Пайтона» говорит о том же ( http://docs.python.org/2/reference/expressions.html#unary-arithmetic-and-bitwise-operations ):

The unary ~ (invert) operator yields the bitwise inversion of its plain or long integer argument. The bitwise inversion of x is defined as -(x+1). It only applies to integral numbers.

zg (zg.livejournal.com)

Комментарий для Евгения Степанищева:

Я, кстати, других платформ и не видел, они бывают?

бывают: http://www.unisys.com/unisys/theme/index.jsp?id=1120000970018010225%26pid=16000034

который по определению обязан работать как NOT(n)=-n-1

ну тогда да, питон может быть только на архитектурах с дополнительным кодом.

Станислав

Спасибо, я как раз такой новичок. Частенько забывал про «минус единицу» в примерах с переменной.

vasa_c

У меня в этом шрифте тильда, как минус показывается.
Так что разницу в примерах, только скопировав увидел :)

Евгений Степанищев (bolknote.ru)

Комментарий для vasa_c:

А что за шрифт выбрался такой неразборчивый?

vasa_c

Комментарий для Евгения Степанищева:

В стилях «11px Monaco,’Trebuchet MS’,Tahoma,sans-serif»
У меня, видимо, Trebuchet срабатывает.
Firefox, Убунта.

Евгений Степанищев (bolknote.ru)

Комментарий для vasa_c:

А что в Линуксе есть из этой шрифтовой семьи, что выглядит хорошо?

Kildor (kildor.ya.ru)

Комментарий для Евгения Степанищева:

DejaVu Sans? Хотя бы просто, поменять местами Требушет и тахому. Или выкинуть его нафиг, пускай браузер сам гротески подставляет.

Евгений Степанищев (bolknote.ru)

Комментарий для kildor.ya.ru:

Поменять не могу. Требушет ЭмЭс отлично смотрится на Винде, а Тахома его перебьёт — на Винде она тоже есть. А ДеджаВю Санс на всех Линуксах есть?

Kildor (kildor.ya.ru)

Комментарий для Евгения Степанищева:

Тады ой ;)

Из википедии:

Некоторые дистрибутивы GNU/Linux (Ubuntu, OpenSUSE, Mandriva Linux) поставляются по умолчанию со шрифтами DejaVu. Также эти шрифты включаются в установочные пакеты OpenOffice.org.

В зависимостях к LibreOffice они тоже есть. И я не могу себе представить десктопного линукса в котором бы не было офиса (опен или либры).

Евгений Степанищев (bolknote.ru)

Комментарий для kildor.ya.ru:

Воткнул перед всеми шрифтами :)

Kildor (kildor.ya.ru)

Комментарий для Евгения Степанищева:

Ещё в одном месте (собственно в блоках кода):
pre code {
  font: 11px Monaco, ’Trebuchet MS’, Tahoma, sans-serif;
}

Евгений Степанищев (bolknote.ru)

Комментарий для kildor.ya.ru:

Готово!

leoleo2(новичок в Python)

По поводу нелогичности записи.

Для меня, например, вполне логично индекс с конца считать, как короткую запись «len(s)-1».
Для тех кто на чём-то си-подобном писал, это очевидная мнемоника, вроде-бы. Или нет? :)

Хотя, конечно, все фломастеры разные на вкус и фокус радует :)

Евгений Степанищев (bolknote.ru)

Комментарий для leoleo2(новичок в Python):

Логичная или нет, люди всё-таки часто путаются. А с такой записью, глядишь, перестанут.

Максим

Лично меня подобная запись заставила бы сбиться с «чтения» и залипнуть; на таком высоком уровне языка ждешь, что битовые операции используются только когда биты и интересуют (двоичный формат разбираем, или конечный автомат какой-нибудь).

Евгений Степанищев (bolknote.ru)

Комментарий для Максим:

Ну больше не ждите, тоже мне проблема.

Популярное