Документация по Python

Списки в Python

В: Документация по Python

Введение

Списки Python — основная структура данных, широко используемая в программах Python. Они встречаются в других языках программирования, часто как динамические массивы. Списки — это изменяемый и последовательный тип данных, который позволяет индексацию и срезы. Список может содержать разные типы объектов, включая другие списки.

Синтаксис

  • [value1, value2, ...]
  • list([iterable])

Замечания

Список это конкретный тип итераций, но не единственный в Python. Иногда лучше использовать множество, кортеж, или словарь.

Списком называют динамические массивы в Python (схоже с  vector<void*> из C++ или Java  ArrayList<Object>). Это не связанный список.

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

Доступ к значениям списка

Списки Python имеют нулевую индексацию и действуют как массивы в других языках.

lst = [1, 2, 3, 4]
lst[0]

>>>Out: 1

lst[1]

>>>Out: 2

Попытка получить доступ к индексу за пределы списка возбудит IndexError .

lst[4]

>>>Out: IndexError: list index out of range

Отрицательные показатели интерпретируются как отсчет от конца списка.

lst[-1]

>>>Out: 4

lst[-2]

>>>Out: 3

lst[-5]

>>>Out: IndexError: list index out of range

Это функционально эквивалентно

lst[len(lst)-1]

>>>Out: 4

Списки позволяют использовать ломтик обозначение , как lst[start:end:step] . Выход среза обозначений представляет собой новый список , содержащий элементы из индекса start до end-1 . Если параметры опущены start значения по умолчанию для начала списка, end в конец списка и step 1:

lst[1:]

>>>Out: [2, 3, 4]

lst[:3]

>>>Out: [1, 2, 3]

lst[::2]

>>>Out: [1, 3]

lst[::-1]

>>>Out: [4, 3, 2, 1]

lst[-1:0:-1]

>>>Out: [4, 3, 2]

lst[5:8]     # так как стартовый индекс больше длины списка, то возвращается пустой список

>>>Out: []

lst[1:10] # то же самое, что опустить конечныый индекс

>>>Out: [2, 3, 4]

Имея это в виду, вы можете распечатать обратную версию списка, вызвав

lst[::-1]    

>>>Out: [4, 3, 2, 1]

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

lst[3:1:-1]

>>>Out: [4, 3]

Использование индексов отрицательных шагов эквивалентно следующему коду:

list(reversed(lst[0:2]))

>>>Out: [2, 1]

Используемые индексы на 1 меньше, чем используемые при отрицательной индексации, и обращены.

Продвинутый срез

Когда списки нарезали, то вызывается __getitem__() метод объекта списка со slice объектом. В Python есть встроенный метод среза для генерации объектов среза. Мы можем использовать это , чтобы сохранить кусочек и использовать его позже , как показано ниже,

data = 'chandan purohit    22 2000'  #предполагаем, что поля данных фиксированной длины 
name_slice = slice(0,19)
age_slice = slice(19,21)
salary_slice = slice(22,None)

#теперь мы можем получить более читабельные срезы
print(data[name_slice])

>>>Out: 'chandan purohit'     

print(data[age_slice])

>>>Out: 22     

print(data[salary_slice])

>>>Out: 2000 

Это может быть очень полезным, предоставляя функциональность для нарезки наших объектов путем переопределения __getitem__ в нашем классе.

Доступ к значениям во вложенном списке

Начиная с трехмерного списка:

alist = [[[1,2],[3,4]], [[5,6,7],[8,9,10], [12, 13, 14]]]

 

Доступ к элементам в списке:

print(alist[0][0][1]) #доступ ко второму элементу первого списка в первом списке

>>>Out: 2


print(alist[1][1][2]) #доступ к третьему элементу второго списка во втором списке

>>>Out: 10

Выполнение вспомогательных операций:

alist[0][0].append(11) #добавляем 11 в конец первого списка в первом списке

print(alist[0][0][2])

>>>Out: 11

Использование вложенных циклов for для печати списка:

#один из вариантов циклического перебора вложенных списков

for row in alist: 
    for col in row:
        print(col)

>>>Out:	[1, 2, 11]
	[3, 4]
        [5, 6, 7]
        [8, 9, 10]
        [12, 13, 14]

Обратите внимание, что эта операция может использоваться для списка включения или даже в качестве генератора для повышения эффективности, например:

[col for row in alist for col in row]

>>Out: [[1, 2, 11], [3, 4], [5, 6, 7], [8, 9, 10], [12, 13, 14]]

Не все элементы во внешних списках должны быть самими списками:

alist[1].insert(2, 15)
#вставляем 15 в третью позицию во втором списке

Еще один способ использовать вложенные циклы. Другой способ лучше, но мне нужно было использовать это иногда:

#менее характерный для Python способ перебора списка

for row in range(len(alist)): 
    for col in range(len(alist[row])):
       print(alist[row][col])

>>>Out: [1, 2]
	[3, 4]
	[5, 6, 7]
	[8, 9, 10]
	15
	[12, 13, 14]

Использование фрагментов во вложенном списке:

print(alist[1][1:])

>>>Out: [[8, 9, 10], 15, [12, 13, 14]]
#Срезы все равно работают

Финальный список:

print(alist)

>>>Out: [[[1, 2], [3, 4]], [[5, 6, 7], [8, 9, 10], 15, [12, 13, 14]]]

Any() и All()

Вы можете использовать all() , чтобы определить , если все значения итератора вычисляют значение True

nums = [1, 1, 0, 1]
all(nums)

>>>Out: False

chars = ['a', 'b', 'c', 'd']
all(chars)

>>>Out: True

Аналогично, any() определяет , является ли одно или более значений в качестве итератора оценки True

nums = [1, 1, 0, 1]
any(nums)

>>>Out: True

vals = [None, None, None, False]
any(vals)

>>>Out: False

Хотя в этом примере используется список, важно отметить, что эти встроенные модули работают с любыми итерациями, включая генераторы.

vals = [1, 2, 3, 4]
any(val > 12 for val in vals)

>>>Out: False

any((val * 2) > 6 for val in vals)

>>>Out: True 

Проверка, если список пуст

Пустота списка связана с булевым значением False , так что вам не надо проверять len(lst) == 0 , а только lst или not lst

lst = []
if not lst:
    print("список пуст")

>>>Out: 'список пуст' 

Проверка наличия элемента в списке

Python позволяет очень просто проверить, есть ли элемент в списке. Просто используйте in операторе.

lst = ['test', 'twest', 'tweast', 'treast']

'test' in lst

>>>Out: True

'toast' in lst

>>>Out: False 

Примечание: in оператора на множествах асимптотически быстрее , чем в списках. Если вам нужно использовать его много раз на потенциально большие списках, вы можете превратить ваш list в set , и проверить наличие элементов на set .

slst = set(lst)
'test' in slst

>>>Out: True 

Сравнение списков

Можно сравнивать списки и другие последовательности лексикографически, используя операторы сравнения. Оба операнда должны быть одного типа.

[1, 10, 100] < [2, 10, 100]
#Истина, поскольку 1 < 2

>>>Out: True  

[1, 10, 100] < [1, 10, 100]
#Ложь, потому что списки равны

>>>Out: False

[1, 10, 100] <= [1, 10, 100]
#Истина, потому что списки равны

>>>Out: True  

[1, 10, 100] < [1, 10, 101]
# Истина, поскольку 100 < 101

>>>Out: True  

[1, 10, 100] < [0, 10, 100]
# Ложь, потому что 0 < 1

 >>>Out: False  

Если один из списков содержится в начале другого, выигрывает самый короткий список.

[1, 10] < [1, 10, 100]

>>>Out: True

Объединение и слияние списков

Самый простой способ конкатенации list1 и list2 :

 merged = list1 + list2 

zip возвращает список кортежей, где I-й кортеж содержит I-й элемент из каждого из аргументов последовательностей или итерируемыми:

alist = ['a1', 'a2', 'a3']
blist = ['b1', 'b2', 'b3']

for a, b in zip(alist, blist):
    print(a, b)

>>>Out: a1 b1
	a2 b2
	a3 b3

 

Если списки имеют разную длину, результат будет включать в себя столько элементов, сколько самый короткий:

alist = ['a1', 'a2', 'a3']
blist = ['b1', 'b2', 'b3', 'b4']
for a, b in zip(alist, blist):
    print(a, b)

>>>Out: a1 b1
	a2 b2
	a3 b3


alist = []
len(list(zip(alist, blist)))

>>>Out: 0

 

Для заполнения списков неравной длины до самого длинного с использованием None из itertools.zip_longest (не забудьте в python 3 импортировать библиотеку)

import itertools

alist = ['a1', 'a2', 'a3']
blist = ['b1']
clist = ['c1', 'c2', 'c3', 'c4']

for a,b,c in itertools.zip_longest(alist, blist, clist):
    print(a, b, c)

>>>Out: a1 b1 c1
	a2 None c2
	a3 None c3
	None None c4
Вставка значений в определенный индекс:
alist = [123, 'xyz', 'zara', 'abc']
alist.insert(3, [2009])
print("Финальный список :", alist)

Результат:

>>>Out: Финальный список: [123, 'xyz', 'zara', 2009, 'abc']

Инициализация списка с фиксированным числом элементов

Для неизменяемых элементов (например , None , строковые литералы и т.д.):

my_list = [None] * 10
my_list = ['test'] * 10

Для изменяемых элементов, та же конструкция , приведет все элементы списка со ссылкой на тот же объект, например, для набора:

my_list=[{1}] * 10
print(my_list)

>>>Out: [{1}, {1}, {1}, {1}, {1}, {1}, {1}, {1}, {1}, {1}]

my_list[0].add(2)
print(my_list)

>>>Out: [{1, 2}, {1, 2}, {1, 2}, {1, 2}, {1, 2}, {1, 2}, {1, 2}, {1, 2}, {1, 2}, {1, 2}]

 

Вместо того , чтобы инициализировать список с фиксированным числом различных изменяемых объектов, используйте:

 my_list=[{1} for _ in range(10)] 

Перебор списка

Python поддерживает использование цикла for непосредственно для  списка:

my_list = ['foo', 'bar', 'baz']
for item in my_list:
    print(item)

>>>Out: foo
	bar
	baz
 

Вы также можете получить позицию каждого элемента одновременно:

for (index, item) in enumerate(my_list):
    print('Элемент в позиции {}: {}'.format(index, item))

>>>Out: Элемент в позиции 0: foo
	Элемент в позиции 1: bar
	Элемент в позиции 2: baz
 

Другой способ итерации списка на основе значения индекса:

for i in range(0,len(my_list)):
    print(my_list[i])

>>>Out: foo
	bar
	baz

Обратите внимание, что изменение элементов в списке во время итерации может привести к неожиданным результатам:

for item in my_list:
    if item == 'foo':
        del my_list[0]
    print(item)

>>>Out: foo
	baz

 

В этом последнем примере, мы удалили первый элемент в первой итерации, это стало причиной пропуска bar.

Длина списка

Используйте len() , чтобы получить одномерный длину списка.

len(['one', 'two']) #возращает 2

>>>Out: 2

len(['one', [2, 3], 'four'])  # возращает 3, а 4

>>>Out: 3  

len() также работает на строках, словарях и других структурах данных, подобных списку.

Обратите внимание, что len() является встроенной функцией, а не методом объекта списка.

Также обратите внимание , что стоимость len() является O(1) , то есть он будет тратить такое же количество времени, чтобы получить длину списка, независимо от его длины.

Список методов и поддерживаемых операторов

Начиная с данным списком a :

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

 

append(value) - добавляет новый элемент в конец списка.

# Append добавляет 6, 7, and 7 к списку
a.append(6)
a.append(7)
a.append(7)
a

>>>Out: [1, 2, 3, 4, 5, 6, 7, 7]

# Добавление к другому списку
b = [8, 9]
a.append(b)
a

>>>Out: [1, 2, 3, 4, 5, 6, 7, 7, [8, 9]]

# Добавляем элемент другого типа, элементы списка не обязательно должны быть одного типа

my_string = "hello world"
a.append(my_string)
a

>>>Out: [1, 2, 3, 4, 5, 6, 7, 7, [8, 9], "hello world"]

Обратите внимание , что append() метод только добавляет один новый элемент в конец списка. Если вы добавляете список в другой список, добавляемый вами список становится единым элементом в конце первого списка.

# добавляем список в другой список
a = [1, 2, 3, 4, 5, 6, 7, 7]
b = [8, 9]
a.append(b)
a

>>>Out: [1, 2, 3, 4, 5, 6, 7, 7, [8, 9]]

a[8] # возращается [8, 9]

>>>Out: [8,9] 

extend(enumerable) - расширяет список путем добавления элементов из другого перечисляемого.

a = [1, 2, 3, 4, 5, 6, 7, 7]
b = [8, 9, 10]

# расширяем список через добавление всех элементов из b

a.extend(b)
a

>>>Out: [1, 2, 3, 4, 5, 6, 7, 7, 8, 9, 10]

# расширяем список элементами из неспискового перечисляемого:
a.extend(range(3))
a

>>>Out: [1, 2, 3, 4, 5, 6, 7, 7, 8, 9, 10, 0, 1, 2]

Списки также могут быть объединены с + оператора. Обратите внимание, что это не изменяет ни один из исходных списков:

a = [1, 2, 3, 4, 5, 6] + [7, 7] + b
a

>>>Out: [1, 2, 3, 4, 5, 6, 7, 7, 8, 9, 10] 

insert(index, value) - вставляет value непосредственно перед указанным значение индекса index. Таким образом, после вставки нового элемента занимает позицию index .

a.insert(0, 0)  # вставляем 0 в позицию 0
a.insert(2, 5)  # вставляем 5 в позицию 2
a

>>>Out: [0, 1, 5, 2, 3, 4, 5, 6, 7, 7, 8, 9, 10] 

remove(value) -  удаляет первое вхождение заданного значения. Если прилагаемое значение не может быть найдено, то вызывается ValueError.

a.remove(0)
a.remove(9)
a

>>>Out: [1, 5, 2, 3, 4, 5, 6, 7, 7, 8, 10]

a.remove(10) # [1, 5, 2, 3, 4, 5, 6, 7, 7, 8]

a.remove(10)
# числе 10 не входит в массив a

>>>Out: ValueError: list.remove(x): x not in list 

reverse() - изменяет список на месте и возвращает None .

a.reverse()
a

>>>Out: [8, 7, 7, 6, 5, 4, 3, 2, 1]

Есть также другие способы реверсирования списка .

count(value) - подсчитывает количество вхождений некоторого значения в списке.

a.count(7) #возращает 2

>>>Out: 2

sort() - сортирует список в числовом и лексикографическом порядке и возвращает None .

a.sort() # сортировка списка в числовом порядке
a

>>>Out: [1, 2, 3, 4, 5, 6, 7, 7, 8]

Списки также могут быть отменены при сортировке с помощью reverse=True , флага в своем sort() методе.

a.sort(reverse=True)
# a = [8, 7, 6, 5, 4, 3, 2, 1]

 

Если вы хотите сортировать по атрибутам элементов, вы можете использовать key ключевого слова аргумента:

import datetime

class Person(object):
    def __init__(self, name, birthday, height):
        self.name = name
        self.birthday = birthday
        self.height = height

    def __repr__(self):
        return self.name

l = [Person("John Cena", datetime.date(1992, 9, 12), 175),
     Person("Chuck Norris", datetime.date(1990, 8, 28), 180),
     Person("Jon Skeet", datetime.date(1991, 7, 6), 185)]

l.sort(key=lambda item: item.name)
l

>>>Out: [Chuck Norris, John Cena, Jon Skeet]

l.sort(key=lambda item: item.birthday)
l

>>>Out: [Chuck Norris, Jon Skeet, John Cena]

l.sort(key=lambda item: item.height)
l

>>>Out: [John Cena, Chuck Norris, Jon Skeet]

В случае списка словарей концепция одинакова:

import datetime

l = [{'name':'John Cena', 'birthday': datetime.date(1992, 9, 12),'height': 175},
 {'name': 'Chuck Norris', 'birthday': datetime.date(1990, 8, 28),'height': 180},
 {'name': 'Jon Skeet', 'birthday': datetime.date(1991, 7, 6), 'height': 185}]

l.sort(key=lambda item: item['name'])
l

>>>Out: [Chuck Norris, John Cena, Jon Skeet]

l.sort(key=lambda item: item['birthday'])
l

>>>Out: [Chuck Norris, Jon Skeet, John Cena]

l.sort(key=lambda item: item['height'])
l

>>>Out: [John Cena, Chuck Norris, Jon Skeet]

Сортировать по субсловарям:

import datetime

l = [{'name':'John Cena', 'birthday': datetime.date(1992, 9, 12),'size': {'height': 175, 'weight': 100}},
 {'name': 'Chuck Norris', 'birthday': datetime.date(1990, 8, 28),'size' : {'height': 180, 'weight': 90}},
 {'name': 'Jon Skeet', 'birthday': datetime.date(1991, 7, 6), 'size': {'height': 185, 'weight': 110}}]

l.sort(key=lambda item: item['size']['weight'])
l

>>>Out: [{'name': 'Chuck Norris',
  'birthday': datetime.date(1990, 8, 28),
  'size': {'height': 180, 'weight': 90}},
 {'name': 'John Cena',
  'birthday': datetime.date(1992, 9, 12),
  'size': {'height': 175, 'weight': 100}},
 {'name': 'Jon Skeet',
  'birthday': datetime.date(1991, 7, 6),
  'size': {'height': 185, 'weight': 110}}]

Лучший способ разобраться с помощью attrgetter и itemgetter

Списки также могут быть отсортированы с помощью функции attrgetter и itemgetter  из модуля оператора. Это может помочь улучшить читаемость и возможность повторного использования. Вот несколько примеров,

from operator import itemgetter,attrgetter

people = [{'name':'chandan','age':20,'salary':2000},
          {'name':'chetan','age':18,'salary':5000},
          {'name':'guru','age':30,'salary':3000}]
by_age = itemgetter('age')
by_salary = itemgetter('salary')

people.sort(key=by_age) #in-place sorting by age
people.sort(key=by_salary) #in-place sorting by salary

 

itemgetter также может быть дан индекс. Это полезно, если вы хотите сортировать на основе индексов кортежа.

list_of_tuples = [(1,2), (3,4), (5,0)]
list_of_tuples.sort(key=itemgetter(1))
print(list_of_tuples)

 >>>Out: [(5, 0), (1, 2), (3, 4)]

Используйте attrgetter, если вы хотите сортировать по атрибутам объекта:

persons = [Person("John Cena", datetime.date(1992, 9, 12), 175),
           Person("Chuck Norris", datetime.date(1990, 8, 28), 180),
           Person("Jon Skeet", datetime.date(1991, 7, 6), 185)] #повторное использования класса Person из примера выше


persons.sort(key=attrgetter('name')) #сортирует по 'name'
by_birthday = attrgetter('birthday')
persons.sort(key=by_birthday) #сортирует по 'birthday'
persons

>>>Out: [Chuck Norris, Jon Skeet, John Cena]

clear() - удаляет все элементы из списка

a.clear()
a

>>>Out: [] 

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

a = ["blah"] * 3
a

>>>Out: ["blah", "blah", "blah"]

b = [1, 3, 5] * 5
b

>>>Out: [1, 3, 5, 1, 3, 5, 1, 3, 5, 1, 3, 5, 1, 3, 5]

Будьте внимательны делая это , если список содержит ссылки на объекты (например , список списков).

Удаление элемента - можно удалить несколько элементов в списке , используя del ключевые слова и ломтик обозначение:

a = list(range(10))
del a[::2]
a 

>>>Out: [1, 3, 5, 7, 9]

del a[-1]
a

>>>Out: [1, 3, 5, 7]
del a[:]

>>>Out: [] 

копирование

Назначение по умолчанию "=" назначает ссылку на исходный список новому имени. Таким образом, исходное имя и новое имя указывают на один и тот же объект списка. Изменения, сделанные с помощью одного из них, будут отражены в другом Это часто не то, что вы хотели.

a = [1, 2, 3, 4, 5]
b = a
a.append(6)
b

>>>Out: [1, 2, 3, 4, 5, 6]

Если вы хотите создать копию списка, у вас есть варианты ниже.

Вы можете нарезать это:

old_list = [1,2,3,4]
new_list = old_list[:]

Вы можете использовать встроенную функцию list():

new_list = list(old_list)

 

Вы можете использовать универсальный copy.copy():

import copy
new_list = copy.copy(old_list) #вставляет ссылки на объекты найденные в оригинале

Это немного медленнее, чем list(), потому что он должен сначала выяснить тип данных old_list.

Если список содержит объекты, и вы также хотите скопировать их, используйте generic copy.deepcopy():

import copy
new_list = copy.deepcopy(old_list) #inserts copies of the objects found in the original.

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

copy() - возвращает неполную копию списка

 aa = a.copy()
 # aa = [1, 2, 3, 4, 5]

Удалить повторяющиеся значения в списке

Удаление повторяющихся значений в списке может быть сделано путем преобразования списка в set (то есть неупорядоченный набор различных объектов). Если необходим список, то множество может быть преобразовано обратно в список с помощью функции list():

names = ["aixk", "duke", "edik", "tofp", "duke"]
list(set(names))

>>>Out: ['duke', 'tofp', 'aixk', 'edik']

Обратите внимание, что при преобразовании списка в набор исходный порядок теряется.

Для того, чтобы сохранить порядок списка можно использовать OrderedDict

import collections
>>> collections.OrderedDict.fromkeys(names).keys()
# Out: ['aixk', 'duke', 'edik', 'tofp'] 

Реверсирование элементов списка

Вы можете использовать функцию reversed, которая возвращает итератор обращенного списка:

rev = reversed(numbers)
rev

>>>Out: [9, 8, 7, 6, 5, 4, 3, 2, 1]

 

Обратите внимание, что список «чисел» остается неизменным этой операцией и остается в том же порядке, в котором он был изначально.

Чтобы изменить на месте, вы можете также использовать в reverse метод .

Вы также можете изменить список (фактически получая копию, исходный список не затрагивается), используя синтаксис срезов, задав третий аргумент (шаг) как -1:

numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9]
numbers[::-1]

>>>Out: [9, 8, 7, 6, 5, 4, 3, 2, 1]
Еще от кодкамп
Замечательно! Вы успешно подписались.
Добро пожаловать обратно! Вы успешно вошли
Вы успешно подписались на кодкамп.
Срок действия вашей ссылки истек.
Ура! Проверьте свою электронную почту на наличие волшебной ссылки для входа.
Успех! Ваша платежная информация обновлена.
Ваша платежная информация не была обновлена.