Я уверен, что есть более простой способ сделать это, что просто не происходит со мной.
Я вызываю кучу методов, которые возвращают список. Список может быть пустым. Если список не пустой, я хочу вернуть первый элемент; в противном случае я хочу вернуть None. Этот код работает:
my_list = get_list()
if len(my_list) > 0: return my_list[0]
return None
Мне кажется, что для этого должна быть простая однострочная идиома, но я не могу об этом думать. Здесь?
Редактировать:
Причина, по которой я ищу здесь однострочное выражение, не в том, что мне нравится невероятно лаконичный код, а в том, что мне приходится писать много такого кода:
x = get_first_list()
if x:
# do something with x[0]
# inevitably forget the [0] part, and have a bug to fix
y = get_second_list()
if y:
# do something with y[0]
# inevitably forget the [0] part AGAIN, and have another bug to fix
То, что я хотел бы сделать, безусловно, может быть выполнено с помощью функции (и, вероятно, будет):
def first_item(list_or_none):
if list_or_none: return list_or_none[0]
x = first_item(get_first_list())
if x:
# do something with x
y = first_item(get_second_list())
if y:
# do something with y
Я опубликовал вопрос, потому что меня часто удивляет, что могут делать простые выражения в Python, и я думал, что написание функции было бы глупо, если бы существовало простое выражение, которое могло бы сработать. Но, увидев эти ответы, кажется, что функция - это простое решение.
источник
next(iter(your_list), None)
вместоfirst_item(your_list)
предположения,your_list
что нетNone
(get_first_list()
иget_second_list()
всегда должны возвращать итеративный).next(iter(your_list))
, поскольку, если вы предоставляете второй аргументiter
, вы говорите, что первый аргумент может быть вызван.None
вот второй параметр дляnext()
, нетiter()
.next()
возвращает второй параметр, если он задан, вместо повышения,StopIteration
еслиyour_list
пусто.Ответы:
Python 2.6+
Если
your_list
можноNone
:Python 2.4
Пример:
Другой вариант - встроить вышеуказанную функцию:
Чтобы избежать,
break
вы можете написать:Куда:
источник
""
в списке есть пустая строка , она отбрасывается и заменяется пустым списком[]
. Если у вас есть 0, также заменяется на[]
. Если у васFalse
там, тоже заменили. И т.д. Вы можете избежать неприятностей в конкретном случае, но это плохая привычка для развития.bool(lst)
говорит нам,len(lst) > 0
не говорит ли нам что-нибудь о том, что элементыlst
содержат, например,bool([False]) == True;
поэтому выражение[False] or []
возвращается[False]
, то же самое для[0] or []
него возвращается[0]
.yield_first()
чтобы избежатьbreak
заявления.Лучший способ это:
Вы также можете сделать это в одну строку, но программисту гораздо сложнее читать:
источник
next(iter(your_list), None)
next(iter(your_list))
достаточноNone
OP. Попробуйте:next(iter([]))
.Это должно работать.
Кстати, я не использовал переменную
list
, потому что это перезаписывает встроеннуюlist()
функцию.Изменить: у меня была немного более простая, но неправильная версия здесь ранее.
источник
Самый идиоматический способ Python - это использовать next () на итераторе, так как список итеративен . так же, как то, что @JFSebastian поместил в комментарии 13 декабря 2011 года.
next(iter(the_list), None)
Это возвращает None, еслиthe_list
пусто. смотрите далее () Python 2.6+или если вы точно знаете,
the_list
не пусто:iter(the_list).next()
смотрите iterator.next () Python 2.2+источник
return l[0] if l else None
если список был libcomp. Когда список на самом деле является genexpr, это даже лучше, так как вам не нужно составлять весь список, как вnext(iter(x for x in range(10) if x % 2 == 0), None)
the_list
не пусто, вы бы написалиthe_list[0]
.Если вы обнаружите, что пытаетесь вырвать первое (или ничего) из понимания списка, вы можете переключиться на генератор, чтобы сделать это следующим образом:
Pro: работает, если бла не индексируется. Con: это незнакомый синтаксис. Это полезно при хакерстве и фильтрации содержимого в ipython.
источник
Решение ОП уже близко, есть всего несколько вещей, которые делают его более питонским.
Во-первых, нет необходимости получать длину списка. Пустые списки в Python оцениваются как False в проверке if. Просто скажи
Кроме того, это очень плохая идея - присваивать переменным, которые пересекаются с зарезервированными словами. "список" является зарезервированным словом в Python.
Итак, давайте изменим это на
Действительно важным моментом, который здесь пропускают многие решения, является то, что все функции / методы Python возвращают None по умолчанию . Попробуйте следующее ниже.
Если вам не нужно возвращать None, чтобы досрочно завершить функцию, нет необходимости явно возвращать None. Очень кратко, просто верните первую запись, если она существует.
И, наконец, возможно, это подразумевалось, но просто чтобы быть явным (потому что явное лучше, чем неявное ), вы не должны заставлять вашу функцию получать список из другой функции; просто передайте это как параметр. Итак, конечный результат будет
Как я уже сказал, OP уже почти у цели, и всего несколько прикосновений придают ему тот вкус Python, который вы ищете.
источник
get_first_item
должен принятьdefault
параметр (напримерdict.get
), который по умолчанию принимает значение None. Таким образом, интерфейс функции явно сообщает, что происходит, еслиmy_list
он пуст.источник
Честно говоря, я не думаю, что есть лучшая идиома: ваша ясна и лаконична - не нужно ничего «лучшего». Может быть, но это действительно дело вкуса, вы можете изменить
if len(list) > 0:
сif list:
- пустым списком всегда будет оценивать Ложь.С другой стороны, Python - это не Perl (не каламбур!), Вам не нужно получать самый крутой из возможных кодов.
На самом деле, худший код, который я видел в Python, также был очень крутым :-) и совершенно не поддерживаемым.
Кстати, большинство решений, которые я видел здесь, не учитывается, когда list [0] оценивается как False (например, пустая строка или ноль) - в этом случае все они возвращают None, а не правильный элемент.
источник
if lst:
а неif len(lst) > 0:
. Кроме того, не используйте ключевые слова Python в качестве имен переменных; это заканчивается слезами. Обычно используетсяL
или вlst
качестве имени переменной для некоторого списка. Я уверен, что в этом случае вы не имели в виду предлагать использоватьlist
в качестве имени переменной, вы просто имели в виду «некоторый список». И +1 для «когда lst [0] оценивается как False».Самый питонский подход - это то, что продемонстрировал самый голосующий голос, и это было первое, что пришло мне в голову, когда я прочитал вопрос. Вот как это использовать, во-первых, если возможно пустой список передается в функцию:
И если список возвращается из
get_list
функции:Другие способы продемонстрировали, чтобы сделать это здесь, с объяснениями
for
Когда я начал пытаться придумать умные способы сделать это, это второе, о чем я подумал:
Это предполагает, что функция заканчивается здесь, неявно возвращая
None
ifget_list
возвращает пустой список. Приведенный ниже явный код в точности соответствуетif some_list
Было также предложено следующее (я исправил неправильное имя переменной), в котором также используется неявное
None
. Это было бы предпочтительнее вышеописанного, так как в нем используется логическая проверка вместо итерации, которая может не произойти. Это должно быть легче сразу понять, что происходит. Но если мы пишем для удобочитаемости и удобства сопровождения, мы также должны добавить явноеreturn None
в конце:нарезать
or [None]
и выбрать нулевой индексЭтот также в наиболее проголосовавшем ответе:
Срез не нужен, и создает дополнительный список из одного элемента в памяти. Следующее должно быть более производительным. Для объяснения
or
возвращает второй элемент, если первый находитсяFalse
в логическом контексте, поэтому, еслиget_list
возвращается пустой список, выражение, содержащееся в скобках, вернет список с «None», к которому затем будет обращаться0
индекс:Следующий использует тот факт, что и возвращает второй элемент, если первый находится
True
в логическом контексте, и поскольку он дважды ссылается на my_list, он ничем не лучше троичного выражения (и технически не является однострочным):next
Тогда у нас есть следующее умное использование встроенного
next
иiter
Чтобы объяснить,
iter
возвращает итератор с.next
методом. (.__next__
В Python 3.) Тогда встроенныеnext
вызовы.next
метода, и если итератор будет исчерпан, возвращает значение по умолчанию мы даем,None
.избыточное троичное выражение (
a if b else c
) и кружение назадБыло предложено ниже, но обратное было бы предпочтительнее, так как логика обычно лучше понимается в положительном, а не отрицательном. Так как
get_list
вызывается дважды, если результат не запомнен каким-либо образом, это будет плохо работать:Лучшее обратное:
Более того, используйте локальную переменную так, чтобы она
get_list
вызывалась только один раз, и у вас сначала было рекомендовано решение Pythonic:источник
Что касается идиомы, есть itertools рецепт называется
nth
.Из рецептов itertools:
Если вам нужны однострочные, рассмотрите возможность установки библиотеки, которая реализует этот рецепт для вас, например
more_itertools
:Доступен другой инструмент, который возвращает только первый названный элемент
more_itertools.first
.Эти itertools масштабируются для любых итераций, а не только для списков.
источник
my_list[0] if len(my_list) else None
источник
len
без причины. Если вы удалите его, приведенный выше код сделает то же самое.Из любопытства я выбрал время для двух решений. Решение, которое использует оператор return для преждевременного завершения цикла for, немного дороже на моей машине с Python 2.5.1, я подозреваю, что это связано с настройкой итерируемого.
Это время, которое я получил:
источник
источник
if len(a) > 0:
но это считается хорошим стилем. Обратите внимание, насколько хорошо это выражает проблему: «попытайтесь извлечь заголовок списка, и если это не сработает, вернитесьNone
». Поиском в Google "EAFP" или посмотрите здесь: python.net/~goodger/projects/pycon/2007/idiomatic/…Кстати, я бы переделал ваш общий поток программ в нечто вроде этого:
(Избегая повторения, когда это возможно)
источник
Как насчет этого:
(my_list and my_list[0]) or None
Примечание: Это должно работать нормально для списков объектов, но может возвращать неправильный ответ в случае списка чисел или строк в комментариях ниже.
источник
([0,1] and 0) or None
!(['','A'] and '') or None
.my_list[0]
оценивается какFalse
, результат должен бытьNone
.my_list[0] if len(my_list) else None
Не уверен, насколько это pythonic, но пока в библиотеке нет первой функции, я включаю ее в источник:
Это всего лишь одна строка (соответствует черному цвету) и позволяет избежать зависимостей.
источник
Используя трюк и / или:
источник
Вероятно, не самое быстрое решение, но никто не упомянул эту опцию:
если
get_list()
можете вернутьNone
вы можете использовать:Преимущества:
-одна линия
-вы просто позвоните
get_list()
один раз-Легко понять
источник
Мой вариант использования был только для установки значения локальной переменной.
Лично я нашел попытку и кроме стиля чище читать
чем нарезать список.
источник
Несколько человек предложили сделать что-то вроде этого:
Это работает во многих случаях, но будет работать, только если list [0] не равен 0, False или пустой строке. Если list [0] равен 0, False или пустой строке, метод по ошибке вернет None.
источник
Вы можете использовать метод извлечения . Другими словами, извлеките этот код в метод, который вы бы затем вызвали.
Я не стал бы пытаться сжать его намного больше, так как кажется, что однострочники труднее читать, чем многословную версию. И если вы используете метод извлечения, это один вкладыш;)
источник
источник
не идиоматический питон, эквивалентный тернарным операторам в стиле C
то есть.
источник