Ответ 5
В Python, как вы получаете последний элемент списка?
Чтобы просто получить последний элемент,
- без изменения списка, и
- при условии, что вы знаете, что в списке есть последний элемент (т.е. он не пуст)
передать -1
в -1
запись:
>>> a_list = ['zero', 'one', 'two', 'three']
>>> a_list[-1]
'three'
объяснение
Индексы и фрагменты могут принимать отрицательные целые числа в качестве аргументов.
Я изменил пример из документации, чтобы указать, на какой элемент в последовательности ссылается каждый индекс, в данном случае в строке "Python"
-1
ссылается на последний элемент, символ 'n'
:
+---+---+---+---+---+---+
| P | y | t | h | o | n |
+---+---+---+---+---+---+
0 1 2 3 4 5
-6 -5 -4 -3 -2 -1
>>> p = 'Python'
>>> p[-1]
'n'
Назначение через повторяемую распаковку
Этот метод может излишне материализовать второй список только для того, чтобы получить последний элемент, но ради полноты (и поскольку он поддерживает любые итерируемые, а не только списки):
>>> *head, last = a_list
>>> last
'three'
Имя переменной head связано с ненужным вновь созданным списком:
>>> head
['zero', 'one', 'two']
Если вы намереваетесь ничего не делать с этим списком, это будет более уместно:
*_, last = a_list
Или, на самом деле, если вы знаете это список (или, по крайней мере, принимаете индексную запись):
last = a_list[-1]
В функции
Комментатор сказал:
Хотелось бы, чтобы в Python была функция для first() и last(), как это делает Lisp... она избавила бы от множества ненужных лямбда-функций.
Это было бы довольно просто определить:
def last(a_list):
return a_list[-1]
def first(a_list):
return a_list[0]
Или используйте operator.itemgetter
:
>>> import operator
>>> last = operator.itemgetter(-1)
>>> first = operator.itemgetter(0)
В любом случае:
>>> last(a_list)
'three'
>>> first(a_list)
'zero'
Особые случаи
Если вы делаете что-то более сложное, вам может показаться более производительным, чтобы получить последний элемент немного по-другому.
Если вы новичок в программировании, вам следует избегать этого раздела, потому что он иначе связывает семантически разные части алгоритмов вместе. Если вы измените свой алгоритм в одном месте, это может оказать непреднамеренное влияние на другую строку кода.
Я стараюсь предоставить предостережения и условия как можно полнее, но я, возможно, что-то упустил. Пожалуйста, прокомментируйте, если вы думаете, что я оставляю оговорку.
нарезка
Срез списка возвращает новый список - так что мы можем срезать от -1 до конца, если мы хотим получить элемент в новом списке:
>>> a_slice = a_list[-1:]
>>> a_slice
['three']
Преимущество в том, чтобы не потерпеть неудачу, если список пуст:
>>> empty_list = []
>>> tail = empty_list[-1:]
>>> if tail:
... do_something(tail)
Принимая во внимание, что при попытке доступа по индексу возникает IndexError
которую необходимо обработать:
>>> empty_list[-1]
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
IndexError: list index out of range
Но опять же, нарезка для этой цели должна быть сделана, только если вам нужно:
- создан новый список
- и новый список будет пустым, если предыдущий список был пустым.
for
петель
Как особенность Python, в цикле for
нет внутренней области видимости.
Если вы уже выполняете полную итерацию по списку, на последний элемент все равно будет ссылаться имя переменной, назначенное в цикле:
>>> def do_something(arg): pass
>>> for item in a_list:
... do_something(item)
...
>>> item
'three'
Это не семантически последняя вещь в списке. Это семантически последняя вещь, с которой было связано имя, item
.
>>> def do_something(arg): raise Exception
>>> for item in a_list:
... do_something(item)
...
Traceback (most recent call last):
File "<stdin>", line 2, in <module>
File "<stdin>", line 1, in do_something
Exception
>>> item
'zero'
Таким образом, это должно использоваться только для получения последнего элемента, если вы
- уже зациклены, и
- Вы знаете, что цикл завершится (не прервется или не выйдет из-за ошибок), в противном случае он будет указывать на последний элемент, на который ссылается цикл.
Получение и удаление
Мы также можем изменить наш оригинальный список, удалив и вернув последний элемент:
>>> a_list.pop(-1)
'three'
>>> a_list
['zero', 'one', 'two']
Но теперь оригинальный список изменен.
(-1
на самом деле является аргументом по умолчанию, поэтому list.pop
можно использовать без аргумента index):
>>> a_list.pop()
'two'
Делайте это только если
- вы знаете, что в списке есть элементы, или готовы обработать исключение, если оно пустое, и
- вы намерены удалить последний элемент из списка, рассматривая его как стек.
Это допустимые варианты использования, но не очень распространенные.
Сохранение остатка обратного на потом:
Я не знаю, почему вы это сделаете, но для полноты, поскольку reversed
возвращает итератор (который поддерживает протокол итератора), вы можете передать его результат next
:
>>> next(reversed([1,2,3]))
3
Так что, как делать обратное:
>>> next(iter([1,2,3]))
1
Но я не могу придумать вескую причину для этого, если позже вам не понадобится остальная часть обратного итератора, который, вероятно, будет выглядеть примерно так:
reverse_iterator = reversed([1,2,3])
last_element = next(reverse_iterator)
use_later = list(reverse_iterator)
и сейчас:
>>> use_later
[2, 1]
>>> last_element
3