Отримання лише елемента з одноелементного списку в Python?


83

Коли відомо, що список Python завжди містить один елемент, чи є спосіб отримати до нього інший доступ, крім:

mylist[0]

Ви можете запитати: "Чому ви хочете?". Допитливість одна. Здається, існує альтернативний спосіб зробити все в Python.


5
Можуть бути й інші варіанти, але, як правило, існує лише один очевидний спосіб це зробити - і, в цьому випадку, ви, здається, це вже знайшли.
ekhumoro

якщо він завжди містить один елемент, то, можливо, a listне найкращий тип даних?
Девід Земенс,

13
@ekhumoro: Я насправді прихильний до методу розпакування послідовностей, оскільки він підтверджує припущення, що послідовність має лише один елемент. mylist[0]вдається, коли у вас є хоча б один елемент, але не скаржиться, якщо у вас насправді було 30 елементів. singleitem, = mylistперевіряє, що у вас є рівно один елемент, ні більше, ні менше.
ShadowRanger

1
@ShadowRanger. Питання явно стосується доступу до єдиного елементу у списку, який, як відомо, вже містить один елемент.
ekhumoro

6
@ekhumoro: Ніякої розбіжності. Я просто віддаю перевагу програмуванню в обороні, тому порушення вимог не проходять мовчки (звичайно, це не вдається, але це не вдається голосно, що набагато легше виявити та виправити, ніж тонкі порушення поведінки). Якби я мав нікель на кожен раз, коли якась "відома" поведінка у виробничому коді виявлялася похибкою неправильно ... Ну, я б, мабуть, не був би багатим , але я б зміг вивести сім'ю до справді гарного вечеря.
ShadowRanger

Відповіді:


123

Розпакування послідовності:

singleitem, = mylist
# Identical in behavior (byte code produced is the same),
# but arguably more readable since a lone trailing comma could be missed:
[singleitem] = mylist

Явне використання протоколу ітераторів:

singleitem = next(iter(mylist))

Руйнівний поп:

singleitem = mylist.pop()

Негативний індекс:

singleitem = mylist[-1]

Встановлюється за допомогою однієї ітерації for(оскільки змінна циклу залишається доступною з останнім значенням, коли цикл завершується):

for singleitem in mylist: break

Багато інших (поєднуючи або варіюючи біти вищезазначеного, або іншим чином покладаючись на неявну ітерацію), але ви розумієте ідею.


6
Не гідне включення в основну відповідь через нестримну маразм: Розпакування параметра до функції одного аргументу (виконано як анонімна лямбда, яка повертає значення для максимально дурного):singleitem = (lambda x: x)(*mylist)
ShadowRanger

6
Перший унікальний тим, що він також піднімається, якщо список містить більше одного елемента.
Neil G,

7
Перший також можна записати як [singleitem] = mylist.
Карстен С

@NeilG: На жаль, це не зовсім унікально; версія "шаленого божевілля" у коментарях теж робить це (як і розпакування за допомогою синтаксису списку, хоча це насправді ідентично першому прикладу поведінки). Зараз я почуваюся трохи брудно.
ShadowRanger

1
@CarstenS: Зазвичай я нахмурююсь, використовуючи []для розпакування послідовностей ( for [i, x] in enumerate(iterable):веде мене до затишку), але так, у разі розпакування одного значення, кінцеву кому можна легко пропустити, і використання дужок виправдане з причин читабельності. Я додав його до відповіді. Дякую!
ShadowRanger

20

Додам, що в more_itertools бібліотеці є інструмент, який повертає один елемент із ітеративного.

from more_itertools import one


iterable = ["foo"]
one(iterable)
# "foo"

Крім того, more_itertools.oneвиникає помилка, якщо ітерабель порожній або містить більше одного елемента.

iterable = []
one(iterable)
# ValueError: not enough values to unpack (expected 1, got 0)

iterable = ["foo", "bar"]
one(iterable)
# ValueError: too many values to unpack (expected 1)

more_itertools є стороннім пакетом > pip install more-itertools

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.