Почему в списке допускаются конечные запятые?

135

Мне любопытно, почему в Python конечная запятая в списке является допустимым синтаксисом, и кажется, что Python просто игнорирует ее:

>>> ['a','b',]
['a', 'b']

Это имеет смысл, когда это кортеж, поскольку ('a')и ('a',)- это две разные вещи, но в списках?

Бурхан Халид
источник
stackoverflow.com/questions/7992559/…
Чиро Сантилли 郝海东 冠状 病 六四 事件 法轮功
7
Завершающая запятая также разрешена в списках на C, C ++, Java, JavaScript и т. Д.
Наюки

Ответы:

223

Основные преимущества заключаются в том, что он упрощает редактирование многострочных списков и уменьшает беспорядок в различиях.

Изменение:

s = ['manny',
     'mo',
     'jack',
]

чтобы:

s = ['manny',
     'mo',
     'jack',
     'roger',
]

включает в себя только однострочное изменение в diff:

  s = ['manny',
       'mo',
       'jack',
+      'roger',
  ]

Это превосходит более запутанный многострочный diff, когда конечная запятая была опущена:

  s = ['manny',
       'mo',
-      'jack'
+      'jack',
+      'roger'
  ]

Последнее различие затрудняет увидеть, что была добавлена ​​только одна строка, а другая строка не изменила содержимое.

Это также снижает риск этого:

s = ['manny',
     'mo',
     'jack'
     'roger'  # Added this line, but forgot to add a comma on the previous line
]

и запускает неявную конкатенацию строкового литерала , производя s = ['manny', 'mo', 'jackroger']вместо предполагаемого результата.

Раймонд Хеттингер
источник
6
В этом есть (самый) смысл, но я был бы очень удивлен, если бы синтаксический анализатор языка был разработан для упрощения различий.
Бурхан Халид,
94
@BurhanKhalid: Разработчики языков - программисты, и программисты делают много вещей, чтобы облегчить себе жизнь.
Greg Hewgill
10
@Burhan Если вы не верите этому объяснению, как насчет того, что так проще определить грамматику? ;) Сравнить List = "[" {Item ","} "]".vs.List = "[" ({Item","}Item|)"]".
Voo
23
Это также упрощает автогенерацию кода для других программ - гораздо проще просто распечатать "\"item\","для каждого элемента, чем печатать "\"item\""для каждого элемента, за которым следуют ","все элементы, кроме последнего.
Адам Розенфилд
9
@Voo Я тоже думал то же самое, но последняя грамматика все равно должна быть определена, потому что это все еще действующий список Python.
Александр Сурафель
34

Это общепринятое синтаксическое соглашение, позволяющее использовать завершающие запятые в массиве, такие языки, как C и Java, допускают это, и Python, похоже, принял это соглашение для своей структуры данных списка. Это особенно полезно при генерации кода для заполнения списка: просто создайте последовательность элементов и запятых, не нужно рассматривать последний как особый случай, в котором не должно быть запятой в конце.

Оскар Лопес
источник
30

Это помогает устранить определенный вид ошибки. Иногда проще писать списки в несколько строк. Но при более позднем обслуживании вы можете захотеть переставить элементы.

l1 = [
        1,
        2,
        3,
        4,
        5
]

# Now you want to rearrange

l1 = [
        1,
        2,
        3,
        5
        4,
]

# Now you have an error

Но если вы разрешите запятые в конце и используете их, вы можете легко изменить порядок строк, не вызывая ошибки.

Кит
источник
1
Это удобно, но этого можно избежать, поставив запятую заранее. Я делаю это все время, когда пишу SQL,
Бурхан Халид
38
Даже если вы добавите запятую к каждому элементу, вам все равно придется опускать запятую в первом элементе.
Greg Hewgill
Линтер должен уметь это ловить, не так ли?
viki.omega9 09
6

Кортеж отличается тем, что ('a')раскрывается с использованием неявного продолжения и ()s в качестве оператора приоритета, тогда как ('a',)относится к кортежу длиной 1.

Ваш исходный пример был бы tuple('a')

richo
источник
('a'),это строка; но я хотел сказать, что конечные запятые в кортежах имеют значение, но в списках они не кажутся, пока Python принимает их.
Burhan Khalid
1
В обоих случаях они молча отбрасываются, просто в кортеже необходимо отличать его от строки в скобках.
richo
tuple('a')это, наверное, плохой пример, потому что в целом tuple(x)и (x,)это не одно и то же. tuple('ab') != ('ab',), tuple('a') == ('a',)только потому, что 'a'это строка длины 1.
Чепнер
Из REPL: >>> ("a",) == ("a") Ложь >>> ("ab",) == ("ab") Ложь >>> ("ab", "bc",) == ("ab", "bc") Истина
Серафья
1

Основная причина - сделать diff менее сложным. Например, у вас есть список:

list = [
    'a',
    'b',
    'c'
]

и вы хотите добавить к нему еще один элемент. Тогда вы в конечном итоге сделаете это:

list = [
    'a',
    'b',
    'c',
    'd'
]

таким образом, diff покажет, что две строки были изменены, сначала добавив ',' в строке с 'c' и добавив 'd' в последней строке.

Итак, python допускает завершение ',' в последнем элементе списка, чтобы предотвратить дополнительные различия, которые могут вызвать путаницу.

Нитиш Чаухан
источник