Как стать автором
Обновить

Комментарии 100

«Первый элемент в списке имеет индекс 0, второй имеет индекс 1, третий это 2, и так далее. Иногда это сбивает с толку новичков python и программирования в целом. Такая система нумерации была принята в то время, когда 1 бит все еще имел большое значение. „
Мне кажется по этому фрагменту должно быть очевидно что это шутка. индекс 0 исторически был не у списка а у массива. И не ради экономии, а потому-что написав array[i] компилятор делал *array+i, причём i был не индекс а смещение.
Об этом, кстати, (различии между offset и index) тоже писалось в обсуждении. Но, по факту, списки унаследовали индексацию с нуля от массивов, но в массивах это было разумно, по указанным вами причинам, а в списках вроде как не совсем (или не всем).
Предложение как раз и заключалось в том, чтобы отказаться от этого наследства и перейти к человечной нумерации.
Да именно, только они всё время на массивы съезжают. Забывая что речь вначале шла о списках. Во второй вашей врезке Гвидо говорит о языках в которых вообще нет списков, а только массивы.
По-моему, весьма сомнительное предложение. Сильно сомневаюсь, что за этим последуют все остальные языки. Это далеко не самая сложная вещь, которую нужно освоить новичкам.
С одной стороны, конечно, человеку, начинающему учить язык так будет понятней, и код будет читабельней. С другой — сколько людей годами считали так, менять этот подход скорее всего будет неприемлемо, так что больше склоняюсь к тому, что не стоит.
Ну можно сделать какой-нибудь флаг, подключающий данную фишку (uses лист_с_единицы) — и всех устроит. Правда потом читать и поддерживать такой код… Я лично за то, чтоб всё оставалось как есть…
Целый час пытаешься отловить баг в чужом коде, прозреваешь, робко идешь в самый верх файла — бьешь себя по голове и ненавидишь Гвидо ван Рассума. :)
#define TRUE FALSE //счастливой отладки суки
А в чем собственно проблема? Введите альтернативный индексер для массива\списка и т.д., скажем [[]] дополнительно к [], который будет просто базироваться на еденице вместо нуля. Таким образом

arr[0] == arr[[1]]

— и никакой двухсмыслицы, и старый код работает, и новчички довольны и бывалым питонистам не надо переучиваться, и конуструкция ИМХО не портит вид кода.
Бред, потому что arr[[1]], это элемент(item) объекта arr по ключу [1] (лист из одного элемента). Да, в листе не могут быть не числовые индексы, но ваше предложение не реализуемо на уровне синтаксического анализатора, питон то динамический.
Я не питонист. Я просто прикинул, как бы я это реализовал, если бы мне в любом языке нужно было сделать имплементацию массива или другого контейнера, который бы начинался с единицы, при это не потеряв совместимости с ранее написанным кодом. Первое что пришло в голову — ввести дополнительный вид синтаксиса индексатора специально под эти цели, и во время компиляции\интерпретации просто преобразовывать arr.indexerBasedOnOne(x) в нечто типа arr[--(x)]. Единственный вопрос — найти синтаксическую конструкцию, интуитивно понятную, без двухзначностей и не занятую под что-то другое, для сокращения этого самого indexerBasedOnOne. А допилить анализатор, чтоб он её узнавал — ИМХО не проблема.
и победила индексация с 0, и это в действительности не так уже важно по большему счету
Непонятно что там за «битва» была. Как выше сказали, с нуля в большинстве языков нумеруется не потому, что это принцип какой-то или потому, что кто-то так придумал наугад, а потому, что это основа индексации. «Сбивает с толку новичков». Даже не верится, что это не шутка)
Согласен насчет новичков, хотя может мне просто в детстве может это было проще принять и свыкнуться с этим.
Индексация с нуля — техническая оптимизация С, который складывал указатели, но она распространилась везде.

Если подумать, это совсем не естественно. Нужно постоянно держать в памяти этот −1. Почему, чтобы взять пятый элемент, я пишу arr[4]? Разве это удобно? Почему, если в списке 10 элементов, то взять десятый (arr[10]) — ошибка? Если беспокоитесь о производительности, храните указатель на начало массива−1.
А может реализовать оба подхода? Программист сам выберет себе нужный.
Наследуем класс list, выставляем ему нужное свойство в конструкторе, например, и список начинается с единицы. А по-умолчанию с нуля.
Будем читать чужой код и каждый раз глядеть в каком состоянии свойство, чтобы понять с чего начинается индексация?
В python есть такая замечательная штука как коллекции, так что не надо никаких свойств.

>>> from collections import NewbieList
>>> a = NewbieList([1, 2, 3])
>>> a[2]
2
>>> a[-1]
3
>>> a[0]
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
IndexError: list index out of range
Зачем такие сложности?
Просто сделать два метода:
getAtIndexBeginningWithZero(0)
и
getAtIndexBeginningWithOne(1)
будут возвращать один и тот, первый (нулевой) элемент :)
Нумерация с ноля — дело привычки. Не думаю что кого- то она напрягает. Ее не стоит менять — больше проблем возникнет.
Вы никогда не пробовали на словах во время перекура коллеге объяснять что хранится в первом, а что во-втором элементе спика… э… простите, я имел ввиду по первому и второму индексу. Все-таки на словах путаница иногда возникает.
Лично у меня уже давно выработалась (противная) привычка говорить не «первый», а «самый первый». Филологи надо мной подтрунивают.
У нас вообще говорят «в нулевом элементе». И все друг друга понимают, довольно удобно.
У нас тоже, но вот кто-то другой вам говорит «первый», и вы уже не знаете, это таки первый или САМЫЙ первый.
Код?! Понятнее?!?!!!
Меня на паскакале очень уставало писать что-нибудь типа
i := n mod 5 + 1;
Вот это постоянное "+1" надоедает.
Нумерация с единицы — неудобна алгоритмически и арифметически.
кто вам мешал в паскале написать var a : array[0..N] of integer;?
Поддержка чужого :(
Своё я пишу с нуля с глубокого детства — именно за счет удобства расчетов.
Ну здесь уже стоит пинать разработчика, а не паскаль. Я наоборот считал возможность задать способ индексации в паскале очень удобной фичей, т.к. иногда архи-полезной оказывалась индексация с -1 (динамическое програмированние, барьерные условия), не говоря уже о всяких array['a'..'z']
Иногда помогают Low и High:
for I := Low(A) to High(A) do ...
Плюс динамические массивы всегда нумеруются с нуля.
А в строках? У паскаля исторически Str[0] = Length(Str). При работе со строками в WinAPI это создает путаницу — у каких-то функций нужно брать строку с нулевого индекса (заморачиваться примерно так: PChar(@Str[0])), а у какие-то — с первого (как все строки в паскале).
Я против нумерации с единицы. С нуля — гораздо понятнее. Тем более что практически во всех языках так и есть — с нуля.
Нет там практически никакой путаницы. И размер в нулевом индексе string — это паскаль, а не Delphi (раз вы говорите о WinAPI). String и ShortString — разные типы.

Если str — это string, то ваше PChar(@Str[0])) никогда не скомпилируется (Fatal Error).

Динамические же массивы и прочие встроенные списки в Delphi (TList, TStringList и т. д.) нумеруются с нуля. Но при этом никто не мешает создать массив [1..10].

Плюс всегда есть Low и High:
for I := Low(A) to High(A) do ...
Ну, на делфи я давненько не писал, так что действительно мог здесь соврать. Однако какая-то путаница со строками там точно была. Использование Low и High после других языков программирования — например, того же си — кажется костылем :-)
Никто не мешает объявлять массивы, начинающиеся с нуля. Единственное, что будет с единицы — строки. Об этом просто надо знать и всё. Вряд ли программист может забыть, с чем именно он сейчас работает (string или же array of char).
Забыл добавить, что конвертация string в PChar происходит автоматически и про это вообще не надо думать (конечно если не стоит задачи работать с памятью на более низком уровне).
А вот здесь вы врете :-) Хотя, может быть, в новых версиях делфи сделали и так, но в семерке при обращении к функциям WinAPI для передачи строкового параметра требовалось приводить тип строки вручную к PChar. Исключение составляли лишь константные строки, не содержащие символов с кодом выше 127.
[0..N-1]
Простите, не удержался :)
т. е. по твоему если индексировать с единицы, то
i := n mod 5;
i будет принимать значения [1..5]?
Проблема обоюдосторонняя. Если нумеровать с 1 — нужно вычитать лишнюю единицу из смещения, а если с 0 — из верхней границы цикла.
Не надо ничего вычитать:
for(i = 0; i < n; i++) { ... }
:)
или так :)
for(i = n-1; i >=0; ++i) {… }
Большой выигрыш?
я не играю. мне нужно считать с конца.
То, о чем вы говорите — частный пример. Чаще надоедает постоянное length−1, и когда знаешь позицию, нужно в уме −1 прибавлять (возьму второй — ага, значит [2−1]). Зато будет первый — первый, второй — второй.
Не помню что бы испытывал с этим трудности, я какой-то не тот новичок?
Если Гвидо может не раздумывая согласится с таким предложением… Питон для меня умер.
Все было наверно так:
"(And to those taking the thread seriously: this is all in jest. We
won't change the indexing base. The idea is so preposterous that the
only kind of response possible is to laugh with it.)

--Guido"
все что получиться из этого «улучшения» так это то что range без полных аргументов исчезнет и будет признан моветоном
Очень удобно сейчас пользоваться срезами, в которых учавствует длинна срезаемого объекта, например, списка.
Потому что при срезе второй индекс указывает границу, но сам элемени с этим индексом исключается.

ведь сейчас — list[: len(list)-2] == list[: -2], тогда как будет — list[: len(list)-2] != list[: -2]

пример не самый показательный, но надеюсь ясный.
Как может программы писать человек, который элементарно не умеет считать с нуля, а не с 1?
Как может писать программы человек, который элементарно не может в HEX-редакторе набить программу которая выведет «Hello, world!».
дада!

c:\>copy con program.exe
> с одной стороны это вроде бы действительно более «человечно»

Я всегда знал что Питон для домохозяек, неспособных к изучению языков.

В английском, например, нет падежей, в некоторых ЯП порядковые числительные начинаются с нуля. В чём проблема?
<trollolo>

Но, как уже отметили выше, алгоритмы становятся проще с массивами, индексирующимися с нуля.
Мдаааа. Эти ребята решили ввести ещё бОльшую путаницу в мир программирования.
И это будет несопоставимо с безобидной нумерацией с нуля.
Только увеличивают энтропию Вселенной почём зря.
а в перле была такая штука
$ARRAY_BASE
$[

This variable stores the index of the first element in an array, and of the first character in a substring. The default is 0, but you could theoretically set it to 1 to make Perl behave more like awk (or Fortran) when subscripting and when evaluating the index() and substr() functions.

но ее выкинули за ненадобностью без всяких революций…
+ на CPAN'e есть Array::Base для желающих революций
Хоть кто-нибудь, перед тем, как писать комментарии, прочтите исходное обсуждение.

<Christopher King>
I think there is some confusion about my idea (I didn't intend it as a joke,
but I was unsure, I was really surprised when Guido endorsed. I think people
have been thinking that my idea was as follows:
>>> items=['a', 'b', 'c']
>>> items.first
'a'
>>> items.second
'b'
>>> items.third
'c'
It is *not* that. I would not want it to be in words.


<Guido van Rossum>
I understood that. — I think others did too but found the proposal so
preposterous that they started posting nonsensical «solutions» based
on an intentionally literalistic misreading of your original post. (If
you think this is odd, realize that Python was named after Monty
Python's Flying Circus — we occasionally like to show off our warped
sense of humor. :-)


Это шутка такая была. Только, боюсь, теперь я весь следующий год буду слышать, что Python переходит на нумерацию с 1 и его пора хоронить.
> Только, боюсь, теперь я весь следующий год буду слышать, что Python переходит на нумерацию с 1 и его пора хоронить.
Ну так и что? Это же весело. :) Да хотя бы эта статья.
Блин, холивар устроили, первый ответ Гвидо — стеб и сарказм, думаю — это 100500-ное предложение ему сделать нумерацию с 1, вот он и ответил неожиданно, «на поржать», посмотреть и постебаться.
За основу берем цифру, равную трём
(С трёх удобней всего начинать),
Приплюсуем сперва восемьсот сорок два
И умножим на семьдесят пять.

(с) Льюис Кэрролл. «Охота на Снарка», 1876
В матлабе нумерация с 1. Не смертельно, но постоянно тут и там возникают неудобные конструкции
Мне кажется, начиная с 1 нумеруют гуманитарии, а программисты, как им и положено, с нуля. А Гвидо молодец, чувство юмора у него есть.
И вроде ж не 1-ое апреля-то…
или первое марта. Смотря как считать. :)
Нулевое, то есть:)
Я просто оставлю этот руби-код здесь.
module Enumerable
  module LameList
    def [](i, *args)
      super(i-1, *args)
    end
    
    def []=(i, *args)
      super(i-1, *args)
    end
  end
  
  def lame
    self.extend(LameList)
  end

end

a = [1,2,3]

puts a[1] # => 2
puts a.lame[1] # => 1
Кому он тут нужен?
Ну надо было куда-то деть его
Счет с нуля — это бред.
Нет, я не спорю, когда пишешь на ассемблере или C, языках, работающих непосредственно с памятью и указателями, использовать индексацию совершенно нормально. Это просто, понятно и адекватно.
Но в языках высокого уровня — это не имеет смысла. Это лексический и математически абсурдно.
Всему виной популярность C. Этот язык стал предком и вдохновителем многих других современных языков, в итоге, даже в языках «очень высокого» уровня мы вместо счета по-прежнему используем индексацию. Мы можем вообще не пользоваться указателями, работой с памятью, но мы по-прежнему должны помнить, что в массиве из N элементов последний элемент будет N-1, а первый — 0.
Это еще, наверное, связано с культурными особенностями. У нас все исторически всегда нумеровалось с единицы. А «у них» с нуля нумеруются не только индексы (массивов, списков и др.), а еще и номера версий, коммиты в репозитории (SVN, HG), этажи, всяческие идентификаторы и серийные номера, и т.д.
Номера версий? Найдите мне хоть один софт с версией 0, 0.0, 0.0.0? Нет таких, есть 1, 0.1, 0.0.1 ну и т.д. С чистого нуля никто не начинает.
История коммитов в SVN начинается с единицы.
вроде как давно пользовались все ICQ то ли 0.95 то ли 0.98
Действительно, насчет SVN вы правы. Но номер версии 0.0.1 тоже для нашей культуры кажется немного странным. Логичнее начинать с 1.0.0.
Иногда думается, что 0.x.x — версии до первого официального релиза. Но это не всегда так, часто версия 0.x.x отмечена на сайте как «стабильный релиз».
Стабильный релиз — это не тот релиз, который содержит всю ту функциональность, которую хотят видеть разработчики.
Мне кажется, что 1.0 — это адекватный, цельный продукт с теми фичами, которые хотят видеть в нем разработчики. А 0.х — это еще не доделанный по тем или иным параметрам продукт. Банального "я не считаю, что это готово" от разработчика достаточно, чтобы не давать версии номер 1.0 ;)
Если бы 1.0 содержало все, что хотят видеть разработчики, то не было б версий 2,3,4,…
Опять таки, я с вами полностью согласен и поддерживаю вашу логику. Давным-давно я переходил с Паскаля на Си, и нулевые индексы во всем мне казались дикими и неестественными. В конце-концов, ведь множество натуральных чисел начинается не с 0, с 1!
Но сейчас уже привык считать все с нуля и раздражаюсь, когда на C/C++ встречаю индексацию чего-нибудь с единицы.

Кстати, с нуля в Linux нумеруются устройства. Это тоже странно. Почему hdd0 или tty0, а не hdd1 или tty1?
Ну, с Линуксом все понятно — говорим Линукс, подразумеваем Юникс; говорим Юникс, подразумеваем Си; ну а где Си, там и индексация с нуля.
Я привык считать с нуля, а потом избавился от этой привычки — заставил себя всегда различать счет и индекс. Кстати, PHP с его «массивами» (индексом может быть любое число, любая строка и т.д.) способствует этому.
Версиями типа 0.1 у некоторых разработчиков принято обозначать альфы/беты нового продукта, который уже можно как-то использовать, но он еще не готов настолько, чтобы стать первой версией себя.
Да, я про это и говорю. Не начинают с нуля — с единицы, десятых, сотых долей — да, начинают. Потому что даже один файл в репозитории — это уже не «ничто», это уже состояние отличное от нуля.
>в итоге, даже в языках «очень высокого» уровня мы вместо счета по-прежнему используем индексацию

Если мы используем индексацию, значит мы производим над индексами какие-то операции. А делать это существенно удобнее, когда индексация идёт с 0. Во всех прочих случая в языках «очень высокого» уровня разумнее пользоваться итераторами и тогда будет вообще по-барабану с какого там индекса начинается счёт.

>но мы по-прежнему должны помнить, что в массиве из N элементов последний элемент будет N-1, а первый — 0.

Да, моск от этого факта просто вскипает :)

Надуманная проблема.
Удобнее? Вы уверены?
Рассмотрим такую тривиальную операцию, как вывод даты.

PHP, выводим название месяца:
$month_names = array("Нулября", "Января", "Февраля", "Марта", "Апреля", "Мая", "Июня", "Июля", "Августа", "Сентября", "Октября", "Ноября", "Декабря").

JS, выводим краткую дату:
var d=new Date();
date_string = d.getDate() + "." + (d.getMonth() + 1) + "." + d.getYear();
document.write(date_string);


Вот почему, ну ПОЧЕМУ в JS день и год считаются с единицы, а месяц с нуля?
Удобнее. Рассмотрите, например, организацию кольцевого буфера. Хранение древовидных структур в линейном массиве и тд и тп. Не нужно заморачиваться с дополнительной еденичкой (где её добавлять, где вычитать — очень много поводов сделать ошибку).

Ваш пример с датами к теме относится весьма слабо. В пехапе вместо фейкового элемента можно было воспользоваться тем, что массивы ассоциативны (и забыть про индексы). Что касается JS — проблема там в том, что они не стали выпендриваться, как пехапешки, а сделали, «как все» :). В большинстве случаев (не только js) месяц с нуля. Скорее всего это как раз чтобы не плодить массивы с фейковым первым (нулевым) элементом. Это довольно частный случай. Вас ведь напрягла эта еденичка? А представьте, морочаться с нею придётся во _всех_ местах с индексной арифметикой, кроме, разве что, исчисления месяцев :).
Количество поводов сделать ошибку — уж точно не больше, чем в случае с индексацией с нуля. Сравним? Предложите структуру, посмотрим каким способом она запишется проще и понятнее.

Я погуглил — в C/C++/Java используется 0-11, в PHP, Python, Ruby, C# используется 1-12
«Рассмотрите, например, организацию кольцевого буфера. Хранение древовидных структур в линейном массиве»…
Вы знаете, сколько существует древовидных структур? Ладно, я сделаю двоичную кучу, для начала.
Блин Гвидо, займись, пожалуйста, параллелизмом, перепили долбаный GCLock…
Меня все устраивает, кроме 0 параллельности питона, кроме как через форки.
And to those taking the thread seriously: this is all in jest. We
won't change the indexing base. The idea is so preposterous that the
only kind of response possible is to laugh with it.

(Коротко — «Ребята, это просто шутка»)

Второй ответ Гвидо, который понял, что некоторые восприняли идею всерьёз:)
Меня все время называли нулем, но лишь потом, когда вырос и стал программистом, понимаю, что ноль, это тот, кто стоит перед первым — просто не всем об этом трубит.
Cool story, bro!
Если это воспринимать не как шутку, то предполагаю 2 форка python 4: pyth0n и py1hon.
Лучше бы скобки разрешили
Каких скобок вам не хватает? Фигурных, как в С-подобных языках?
В QBASIC был такой оператор «OPTION BASE», позволявший выставлять значение начального индекса для массивов. Хочешь — нуль, а хочешь — единица.

Заметочка о нем: ъ.tv/i5

Я к чему?.. Если кому-то очень хочется с нуля, ну сделайте такой «переключатель», да балуйтесь индексами, начинающимися с единицы.
Последнее предложение получилось в армейском стиле :) «Вывести бы вас в чисто поле, поставить лицом к стенке да пустить пулю в лоб!».
Да он и до Visual Basic дожил, выкинули его только при переходе на .NET.
Ну а че, надо делать форк питона с нумерацией начиная с единицы :)))
Очень засомневался в достоверность поста. Оказалось — утка.

Кстати, если вы решили начать программировать и не можете запомнить, что нумерация индекса массива начинается с 0, то у меня для вас плохие новости.
вопрос не в «можете запомнить», а в «есть ли в этом смысл, отличный от „просто так сложилось“»
Переменная массива — указатель на первый элемент массива в памяти. Индекс — сдвиг относительно первого элемента. Нет смысла?
Сдвиг — это смещение (offset), а индекс — это порядковый номер. Всякие высокоуровневые абстракции (о которых и говорится) вовсе не непрерывно размещены в памяти. Так что да, нет смысла.
Мне не понятно почему возмущение такое, по этому поводу?

P.S. Ну давайте тогда массивы будут нумероваться с нуля, а контейнеры объектов с единицы. Что бы не было путаницы ;)!
Зарегистрируйтесь на Хабре, чтобы оставить комментарий

Публикации

Изменить настройки темы

Истории