Математический практикум по Питону.
Показано как добавлять/удалять элементы из списка, рассмотрены арифметические операции над списком, и упорядочивание/сортировка. Вводятся генераторы, range, фильтры и итераторы (iter, next). Объяснено что такое адрес объекта (id) и в чем разница между равенством и идентичностью объектов (is). Показано как копировать списки.
Ключевые слова: append, pop, extend, insert, del, id, copy, deepcopy, reverse и sort.
Это предварительная версия! Любые замечания приветствуются.
Список не только хранить данные, но и подддерживает добавление новых элементов (в его конец), а также извлечение и удаление подсписков. по мимо этого упорядочивать элементы.
# Введем список.
l = [5, 23, -11, 23, 44]
len( l ) # Размер исходного списка.
5
Список на то и списк, что к нему можно добавить элемент (в его конец).
l.append(7) # Метод append, аргумент -- добавляемый элемент.
l # Элемент 7 добавился в конец (т.е. самый правый) списка.
[5, 23, -11, 23, 44, 7]
len( l ) # Размер списка увеличился на 1 элемент.
6
Взять элемент с конца списка. Полезно при однократной обработки элементов (обработал и забыл).
# Испольуется метод pop. Элемент будет возвращен как значение.
l.pop() # Возвращаются с конца, т.е. в обратном порядке от добавления.
7
После взятия элемента список уменьшился.
l
[5, 23, -11, 23, 44]
# Список будет уменьшен на один элемент, т.е. сокращен по размер.
l, len(l) # Получили исходный список.
([5, 23, -11, 23, 44], 5)
# На самом деле извлесть элемент можно не только с конца.
l.pop(2) # Например в даном случае извлекается 2 элемент.
# Обычная версия эквивалентна pop(-1). Индексы нумеруются с 0.
-11
l # Выведем элементы оставшегося списка.
[5, 23, 23, 44]
Цикл обхода
l = [5, 23, -11, 23, 44]
Можно написать цикл обхода по всем элементам. Элементы обходятся в обратном порядке.
while len(l) > 0:
a = l.pop()
print(a)
44 23 -11 23 5
После такого цикла, т.е. после извлечения всех элементов он очевидно будет пустым.
l
[]
l.pop()
--------------------------------------------------------------------------- IndexError Traceback (most recent call last) <ipython-input-13-33a5ac1f2384> in <module> ----> 1 l.pop() IndexError: pop from empty list
Восстановим его.
l = [5, 23, -11, 23, 44]
while len(l) > 0:
a = l.pop(0)# берем с начала списка.
print(a)
5 23 -11 23 44
Расширение списка
l = [5, 23, -11, 23, 44]
# Добавим два элемента?
l.append([5, 3]) # Или как?
l # Добавили, но наверно не так как хотели.
[5, 23, -11, 23, 44, [5, 3]]
К списку был добавлен элемент [5,3].
# Добавляет в конец текущего списка элементы из другого списка.
l.extend([23,3]) # Аргумент метода extend должен быть списом.
l
[5, 23, -11, 23, 44, [5, 3], 23, 3]
d = [6, -4] # Например, другой список.
l.extend( d ) # Добавляем его элементы в конец нашего списка.
l
[5, 23, -11, 23, 44, [5, 3], 23, 3, 6, -4]
d.extend(6) # Когда аргумент не явлется списком, то ошибка.
--------------------------------------------------------------------------- TypeError Traceback (most recent call last) <ipython-input-20-6e3cea4c499b> in <module> ----> 1 d.extend(6) # Когда аргумент не явлется списком, то ошибка. TypeError: 'int' object is not iterable
Вставляет элемент на заданное место и сдвигает другие (далее следующие) дальше. Фактически раздвигает элементы и освобождает себе место. Потом его занимает.
l
[5, 23, -11, 23, 44, [5, 3], 23, 3, 6, -4]
l.insert(2, 101) # Используется метод insert.
l # Первый Аргумент указывет куда, второй что добавляемые элементы.
[5, 23, 101, -11, 23, 44, [5, 3], 23, 3, 6, -4]
l.insert(5, [-5, -6]) # Так не получится.
l # Точнее вряд ли то, что мы ожидали.
[5, 23, 101, -11, 23, [-5, -6], 44, [5, 3], 23, 3, 6, -4]
Вставить
пример
l
[5, 23, 101, -11, 23, [-5, -6], 44, [5, 3], 23, 3, 6, -4]
l.index(44)
6
# Вставили число 9 перед первым вхождением 44.
l.insert( l.index(44), 9)
l
[5, 23, 101, -11, 23, [-5, -6], 9, 44, [5, 3], 23, 3, 6, -4]
Упр. Есть упорядоченный список, например = [1,3,5,7,9,11] Нужно запросить у пользователя число и вставить его в нужное место данного списка., т.е. фактически сначала найти место/индекс, фактически реализовать вручную метод insert
l
[5, 23, 101, -11, 23, [-5, -6], 9, 44, [5, 3], 23, 3, 6, -4]
l[3:6]
[-11, 23, [-5, -6]]
# Удаляет элемент с данным индексом (ами)
del l[3:6]
l
[5, 23, 101, 9, 44, [5, 3], 23, 3, 6, -4]
# Удаляем один или более разрозненных элементов.
del l[1], l[1] # Подумай почему индекс указан ожин и тот же.
l
[5, 9, 44, [5, 3], 23, 3, 6, -4]
l[1]=23
l
[5, 23, 44, [5, 3], 23, 3, 6, -4]
# Вырезаем (удаляем) первый элемент из списка равный данному.
l.remove(23)
l
[5, 44, [5, 3], 23, 3, 6, -4]
Элемент должен быть в списке.
[1,2,3].remove(0)
--------------------------------------------------------------------------- ValueError Traceback (most recent call last) <ipython-input-34-176143c6ad97> in <module> ----> 1 [1,2,3].remove(0) ValueError: list.remove(x): x not in list
dd = [2]
dd
[2]
del dd[0] # При удалении последнего элемента сам список остается.
dd # Пустой, но список.
[]
f = [2, 7, 8]
f
[2, 7, 8]
Можно все радикально очистить.
f.clear()
f # Список пуст
[]
# Присваиваем новый объект,
f = [] # пустой список.
f
[]
Упр. В чем разница между присвоением пустого списка с методом clear? Возможно лучше сначала весь ноутбук прочесть.
Списки нужны для хранения данных. Если мы захотим все числа умножить на два, то возможно мы бы написали:
l
[5, 44, [5, 3], 23, 3, 6, -4]
l * 2 # Хотим умножить все элементы списка на два.
[5, 44, [5, 3], 23, 3, 6, -4, 5, 44, [5, 3], 23, 3, 6, -4]
И увидели бы результат, который скоре всего не соответсвует нашим ожиданиям. Дело в том, что список является объектом сам по себе. Поэтому он имеет свои смысловые нагрузки на операции. Например, + объединяет списки (конкатенация), точнее она ставит один список (второй) в конец другому (первому).
По факту произошло дублирование списка.
Но сам список остался неизменным.
l
[5, 44, [5, 3], 23, 3, 6, -4]
Конкатенация, один список добавили в конец к другому.
[1, -5] + [-7, 5, 18] # Получили новый список
[1, -5, -7, 5, 18]
l + [2] # как append добавили 2 в конец списка.
[5, 44, [5, 3], 23, 3, 6, -4, 2]
Операция выполнена, но не сохранена.
l # Поэтому старое значение списка l.
[5, 44, [5, 3], 23, 3, 6, -4]
Операции умножение соответствует многократной конкатенации (т.е. повтору) самого себя:
[2, 5] * 3
[2, 5, 2, 5, 2, 5]
# Только для целых чисел.
l * 2. # Для плавающей точки будет даже ошибка.
--------------------------------------------------------------------------- TypeError Traceback (most recent call last) <ipython-input-48-26f6c6993bb5> in <module> 1 # Только для целых чисел. ----> 2 l * 2. # Для плавающей точки будет даже ошибка. TypeError: can't multiply sequence by non-int of type 'float'
Упр. Как циклически сдвинуть элементы списка? Последнее подразумевает, что все элементы сдвинутся на один вперед, а первый попадет в конец.
[3,5,6] - [6] # Списки вычетать нельзя.
--------------------------------------------------------------------------- TypeError Traceback (most recent call last) <ipython-input-49-8e7e9ddd96ad> in <module> ----> 1 [3,5,6] - [6] # Списки вычетать нельзя. TypeError: unsupported operand type(s) for -: 'list' and 'list'
Бывает важным скопировать объект. Рассмотрим на примере списка какие с этим связаны нюансы.
Упорядочивание
Возьмем, например, список имен.
names = ['Максим', 'Дима', 'Алексей', 'Олег']
names
['Максим', 'Дима', 'Алексей', 'Олег']
type(names)
list
Раз есть операция сравнения на строками, то объекты списка можно упорядочить (отсортировать).
names.sort() # сортируем объекты в списке,
names # т.е. имена в списке.
['Алексей', 'Дима', 'Максим', 'Олег']
misc = [4, 'Максим', 'Дима', 11]
Отсортировать объекты без определенной над объектами операции сравнения нельзя.
# В частности, ранородные: содержащие и цифры и строчки.
misc.sort()
--------------------------------------------------------------------------- TypeError Traceback (most recent call last) <ipython-input-54-8265c7a41d41> in <module> 1 # В частности, ранородные: содержащие и цифры и строчки. ----> 2 misc.sort() TypeError: '<' not supported between instances of 'str' and 'int'
# Действительно. Нельзя сравнить.
3 < "Дима" # Пытаемся сравнить цифру и слово.
--------------------------------------------------------------------------- TypeError Traceback (most recent call last) <ipython-input-55-79647bb5cad7> in <module> 1 # Действительно. Нельзя сравнить. ----> 2 3 < "Дима" # Пытаемся сравнить цифру и слово. TypeError: '<' not supported between instances of 'int' and 'str'
# Превратим цифры в строчки.
misc = ['4', 'Максим', 'Дима', '11']
misc.sort() # Теперь сработала сортировка.
misc # Она считает, что цифры идут раньше букв.
['11', '4', 'Дима', 'Максим']
Простая копия списка делается с помощью метода copy.
l = [5, -1, 6, -3, 4]
e = l.copy() # Копия списка.
Упорядочиваем (сортируем) сам список.
l.sort() # Копию не создает.
l # Изменяется сам список.
[-3, -1, 4, 5, 6]
Список e остался неизменным.
e
[5, -1, 6, -3, 4]
# Упорядочивание в обратом порядке.
e.sort( reverse = True )
e
[6, 5, 4, -1, -3]
Порядок
e = [5, 4, 11]
ee = e.copy()
# Организует список в обратном направлении.
e.reverse() # Метод reverse изменяет сам список.
e
[11, 4, 5]
Можно и так, но будет создан новый список.
q = ee[::-1] # Сложный индекс полезная вещь!
q
[11, 4, 5]
Списки q и e имеют одинаковые значения
q==e
True
Но это разные объекты. Для такой проверки есть специальный оператор питона.
q is e
False
Первоначальный же список остался вообще без изменений.
ee
[5, 4, 11]
Подсчет
f = [5, 8, 5, -1, 14, 5.0]
Метод count возвращает количество раз объект встречается.
f.count(5) # Подсчитаем встречаемости числа 5.
3
# Для отсутствующего в списке объекта.
f.count( 7 ) # Ествественно возвращается 0.
0
# Не возбраняется искать объекты произвольной структуры.
f.count( 'a' ) # Ищем строку a.
0
На примере списка покажем, что в питоне в переменных хранятся не сами значения, а ссылки на объекты. Соответственно при копировании копируются именно ссылки на один и тот же объект, а не сам объект.
Изменение значение элемента списка
l = [5, 44, [5, 3], 23, 3, 6, -4]
l
[5, 44, [5, 3], 23, 3, 6, -4]
d = l
d
[5, 44, [5, 3], 23, 3, 6, -4]
d[1] = 11
d
[5, 11, [5, 3], 23, 3, 6, -4]
l # Сюрприз! Значение в l тоже поменялось.
[5, 11, [5, 3], 23, 3, 6, -4]
Опустошение списка
f = [1,2,3]
d = f
d
[1, 2, 3]
f = []
f
[]
Список d остался неизменным.
d
[1, 2, 3]
Попробуем теперь иначе.
f = d
f, d
([1, 2, 3], [1, 2, 3])
f.clear()
Оба стали пустыми.
f, d
([], [])
Исправление проблемы
В питоне на самом деле в переменных хранятся не значения, а ссылки на объекты. Поэтому при копировании переменной копируется ссылка. Для правильного копирования необходимо сам объект скопировать.
l
[5, 11, [5, 3], 23, 3, 6, -4]
e = l.copy() # Делаем копию списка.
e
[5, 11, [5, 3], 23, 3, 6, -4]
e[1] = 22
e
[5, 22, [5, 3], 23, 3, 6, -4]
l # А так все как надо: элемент не изменился.
[5, 11, [5, 3], 23, 3, 6, -4]
Про оператор id
# Возвращает уникальный идентификатор --
id(l) # handler -- объекта.
140528579080648
d = l
# Идентификаторы при присвоение значения переменной совпадают.
id(l) == id(d) # в d ранее присвоили l.
True
a = id(l) # Сохраним значение идентификатора до изменения.
l[2] = 5 # Изменяем содержимое списка.
b = id(l) # сохраняем идентификатора и после изменения.
l
[5, 11, 5, 23, 3, 6, -4]
# Изменение объектв не ведет к изменению его идентификатора.
a == b
True
a = id(l) # Аналогично.
l.append(-3)
b = id(l)
l
[5, 11, 5, 23, 3, 6, -4, -3]
a == b # Даже при добавлении элемента
True
Вернемся к нашим спискам
l, e
([5, 11, 5, 23, 3, 6, -4, -3], [5, 22, [5, 3], 23, 3, 6, -4])
print("id of id", id(l), ",", "id of e", id(e), '. Они равны?:', id(l) == id(e))
# При создании копии самого объекта идентификатор изменился.
id of id 140528579080648 , id of e 140528630338184 . Они равны?: False
Double trick
t = [1, 2, 3]
q = [t] * 2
q
[[1, 2, 3], [1, 2, 3]]
q[0]
[1, 2, 3]
q[0][1]
2
q[0][1] = 11
q
[[1, 11, 3], [1, 11, 3]]
Упр. Объясни почему у списка q изменение произошло в двух местах.
Но, не все так просто
# Берем список с подсписком.
f = [ 5, [3, -2], [5, 8]]
g = f.copy() # Делаем копию его.
g[0] = 1 # Сделали изменение.
g
[1, [3, -2], [5, 8]]
f # Все ок.
[5, [3, -2], [5, 8]]
g[1] # Под индексом 1 у нас список.
[3, -2]
# А теперь добавили к списку под индексом 1 элемент
g[1].append(-1) # -- число -1.
g # Все ок.
[1, [3, -2, -1], [5, 8]]
# Посмотрим что с исходным списоком.
f # Хм....у исходного первый индекс тоже изменился... непорядок!
[5, [3, -2, -1], [5, 8]]
id(f) == id(g)
False
id(f[1]) == id(g[1])
True
from copy import deepcopy # Палочка выручалочка.
g = deepcopy( f )
g[1].append( -9 )
g
[5, [3, -2, -1, -9], [5, 8]]
f # Ура! Первый индекс не изменился.
[5, [3, -2, -1], [5, 8]]
id(f[1]) == id(g[1])
False
Упр. Почему copy не спасает?
Знак == позволяет проверить равенство объектов по сути, т.е. по смысловому значению. А не исходя из внутреннего представления объекта.
l0, l1 = [1, [4, 7], 7], [1, [4, 7], 7]
id(l0) == id(l1)
False
Равенство, в частности, списков проверяется по содержимому.
#[1, [4, 7], 7] == [1, [4, 7], 7]
l0 == l1
True
Даже если числа имеют разный тип. Всегда можно тип привести.
[1, [4, 7], 7.] == [1, [4., 7], 7] # Один фиг же что 4, что 4..
True
7 == 7.
True
Если объекты разные по сути, то и такой ответ.
[1, [4, 7], 7] == [1, [5, 7], 7] # 4 же не равно 5.
False
В строковых выражениях тоже будет работать.
['aa',['bb']] == ['aa', ['bb']]
True
['aa',['bb']] == ['aa', ['bb ']]
# Во втором есть пробел
False
a = [1, 2, 5]
b = a.copy()
a == b # Объекты равны несмотря на то, что они представлены разными списками, т.е. объектами.
True
id(a) == id(b) # Как мы помним у объектов a и b разный handler (поэтому это и разные объекты).
False
Для проверки ссылаются ли переменные на один объект используется оператор is.
a is b # Фактически эквиваленто id(a) == id(b).
False
c = a
a is c
True
Оператор is очень важен для Питона!
Строчки
что же там со строчками...
s = 'некая строка'
s + '66' # Создалась новая строка.
'некая строка66'
s # s не изменился.
'некая строка'
id(s)
140528578566064
id(s + '66')
140528578724200
id(s), id(s + '66')
# Индекс первого объека сохранился, а вот второго каждый раз новый.
(140528578566064, 140528578725032)
?????
Object `???` not found.
id('aa science')
140528630390000
id('aa science'), id('aa science')
# У этих двух идекс новый, но в рамках одной ячейке совпадает...
(140528579337904, 140528579337904)
При разных строчках будут различаться.
id('aa science'), id('bb science')
(140528630339248, 140528578684784)
Касательно равенства
В питоне, в согласии с традиционными языками программирования, строки константны, но хранятся они в разных местах.
str1 = 'строка'
str2 = 'строка'
id(str1) == id(str2)
False
str1 == str2
True
У чисел тоже есть id. т.е. можно считать что они тоже где-то хранятся. Но в фиксированном месте.
id(6)
94856212474560
Идентификаторы совпадают из разных ячеек.
# Например, схожая вещь для целых чисел.
id(6), id(3+3)
(94856212474560, 94856212474560)
id(7)
94856212474592
Фактически у каждого числа свой идентификатор. Может там что и закодировано.
id(6),id(7),id(8),id(-1)
(94856212474560, 94856212474592, 94856212474624, 94856212474336)
id(5) # Не совпадает с id(6)
94856212474528
Утрируя, в этом смысле отдельные цифры являются константными объектами.
6 = 7 # Нельзя присвоить 6 7.
File "<ipython-input-142-d3ec8f1cc0c4>", line 1 6 = 7 # Нельзя присвоить 6 7. ^ SyntaxError: can't assign to literal
По аналогии с разными строчками идентификаторы совпадают.
id([1,2]), id([2])
(140528630388232, 140528630388232)
Если скопировать в отдельные переменные, то не будут.
ff1 = [1,2]
ff2 = [2]
id(ff1), id(ff2)
(140528578632008, 140528630387464)
Упр. Почему у предыдущих один и тот же id?
Сравнение нужно делать аккуратно.
["строка"], ["строка"][0] # Это понятно.
(['строка'], 'строка')
['строка'] == ["строка"][0]
False
Сравним id списока со строкой и самой строки.
id( ['строка'] ) == id( ["строка"][0] )
# Конечно не равны.
False
Интервал индексов
От 0 до некого числа не включительно.
r = range(10)
r
range(0, 10)
type(r)
range
Можно либо сразу по нему выполнить проход циклом:
for i in r:
print(i, ' ', end='')
0 1 2 3 4 5 6 7 8 9
либо явно так:
for i in range(10):
print(i, ' ', end='')
0 1 2 3 4 5 6 7 8 9
А можно превратить в список:
list( r )
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
Можно указать и начальное значение.
for i in range(3, 10):
print(i, ' ', end='')
3 4 5 6 7 8 9
В расширенном варианте указывается от, до и шаг.
for i in range(-5, 17, 3):
print(i, ' ', end='')
-5 -2 1 4 7 10 13 16
В качестве аргументов использует только целые числа
range(0, 1, 0.1)
--------------------------------------------------------------------------- TypeError Traceback (most recent call last) <ipython-input-155-228cad29e8de> in <module> ----> 1 range(0, 1, 0.1) TypeError: 'float' object cannot be interpreted as an integer
Потребление памяти
import sys
r = range(10000000)
sys.getsizeof( r )
48
lll = list( r )
При создании списка потребуется память для хранения всех этих сгенерированных значений.
mem = sys.getsizeof( lll )
mem
90000112
В объеме:
print( mem/1024/1024, "МБ" )
85.83079528808594 МБ
Удалим такую переменную.
del lll
Итого, смысл генераторов в том, что их элементы обрабатываются по очереди, но не через явный список. Но конечно есть исключения.
Если у нас уже есть генератор, то мы можем построить наш на его основе.
l = range(-90, 100, 20)
g = 2*i for i in l
File "<ipython-input-164-44baea6d1042>", line 1 g = 2*i for i in l ^ SyntaxError: invalid syntax
g = (2*i for i in l)
g
<generator object <genexpr> at 0x7fcf5c04d0f8>
Чтобы увидеть значения превратим с список.
list(g)
[-180, -140, -100, -60, -20, 20, 60, 100, 140, 180]
list(g)
[]
g = (2*i for i in l)
Можно сразу
[2*i for i in l]
[-180, -140, -100, -60, -20, 20, 60, 100, 140, 180]
Так можно получить равномерно расположенные точки на интервале от -1 до 1.
[i/100 for i in range(-100, 110, 10)]
[-1.0, -0.9, -0.8, -0.7, -0.6, -0.5, -0.4, -0.3, -0.2, -0.1, 0.0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0]
А так интервал [50 51]
В range нельзя использовать дробные числа. Можно как раз создать собственный генератор, который их и сделает.
[i/100 + 50 for i in range(0, 110, 10)]
[50.0, 50.1, 50.2, 50.3, 50.4, 50.5, 50.6, 50.7, 50.8, 50.9, 51.0]
Упр. Как получить список равномерно заполняющих точек n на привольном интервал (a,b).
Выполнить операции по раздельному.
h = [i/1000 for i in range(0, 1010, 10)]
g = [j + 50 for j in h]
g[::10] # Так удобнее выводить большой список.
[50.0, 50.1, 50.2, 50.3, 50.4, 50.5, 50.6, 50.7, 50.8, 50.9, 51.0]
sys.getsizeof( h ), sys.getsizeof( g )
(912, 912)
Можно и в одну строку. Но все равно будет потребляться такой же объем памяти.
[j + 50 for j in [i/1000 for i in range(0, 1010, 10)]]
g[::10]
[50.0, 50.1, 50.2, 50.3, 50.4, 50.5, 50.6, 50.7, 50.8, 50.9, 51.0]
Без преобразования в список промежуточных этапов будет так
h = (i/1000 for i in range(0, 1010, 10))# Генератор, а не список!
g = (j + 50 for j in h)# Генератор, а не список!
g
<generator object <genexpr> at 0x7fcf5c04d8e0>
Необходимый объем памяти не зависит от размера данных.
sys.getsizeof( h ), sys.getsizeof( g )
(88, 88)
Так вывести не получится:
[g]
[<generator object <genexpr> at 0x7fcf5c04d8e0>]
А так можно
list(g)
[50.0, 50.01, 50.02, 50.03, 50.04, 50.05, 50.06, 50.07, 50.08, 50.09, 50.1, 50.11, 50.12, 50.13, 50.14, 50.15, 50.16, 50.17, 50.18, 50.19, 50.2, 50.21, 50.22, 50.23, 50.24, 50.25, 50.26, 50.27, 50.28, 50.29, 50.3, 50.31, 50.32, 50.33, 50.34, 50.35, 50.36, 50.37, 50.38, 50.39, 50.4, 50.41, 50.42, 50.43, 50.44, 50.45, 50.46, 50.47, 50.48, 50.49, 50.5, 50.51, 50.52, 50.53, 50.54, 50.55, 50.56, 50.57, 50.58, 50.59, 50.6, 50.61, 50.62, 50.63, 50.64, 50.65, 50.66, 50.67, 50.68, 50.69, 50.7, 50.71, 50.72, 50.73, 50.74, 50.75, 50.76, 50.77, 50.78, 50.79, 50.8, 50.81, 50.82, 50.83, 50.84, 50.85, 50.86, 50.87, 50.88, 50.89, 50.9, 50.91, 50.92, 50.93, 50.94, 50.95, 50.96, 50.97, 50.98, 50.99, 51.0]
h = (i/1000 for i in range(0, 1010, 10))# Генератор, а не список!
g = (j + 50 for j in h)# Генератор, а не список!
g
<generator object <genexpr> at 0x7fcf5c04d888>
Циклом вывести можно так:
for i in g:
print(i)
50.0 50.01 50.02 50.03 50.04 50.05 50.06 50.07 50.08 50.09 50.1 50.11 50.12 50.13 50.14 50.15 50.16 50.17 50.18 50.19 50.2 50.21 50.22 50.23 50.24 50.25 50.26 50.27 50.28 50.29 50.3 50.31 50.32 50.33 50.34 50.35 50.36 50.37 50.38 50.39 50.4 50.41 50.42 50.43 50.44 50.45 50.46 50.47 50.48 50.49 50.5 50.51 50.52 50.53 50.54 50.55 50.56 50.57 50.58 50.59 50.6 50.61 50.62 50.63 50.64 50.65 50.66 50.67 50.68 50.69 50.7 50.71 50.72 50.73 50.74 50.75 50.76 50.77 50.78 50.79 50.8 50.81 50.82 50.83 50.84 50.85 50.86 50.87 50.88 50.89 50.9 50.91 50.92 50.93 50.94 50.95 50.96 50.97 50.98 50.99 51.0
Фильтр
Сформировать список четных чисел:
[i for i in range(0, 17) ]
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]
[i for i in range(0, 17) if (i%2)==1 ]
[1, 3, 5, 7, 9, 11, 13, 15]
[i for i in range(-100, 100) if -5<i<9 ]
[-4, -3, -2, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8]
Поиск корня
Найдем корень методом линейного перебора с неким шагом.
import math as mt
x = [i/1000 + 1 for i in range(0, 1010, 10)]
xx = [i for i in x if abs(mt.cos(i)) < 0.1 ]
xx
[1.48, 1.49, 1.5, 1.51, 1.52, 1.53, 1.54, 1.55, 1.56, 1.5699999999999998, 1.58, 1.5899999999999999, 1.6, 1.6099999999999999, 1.62, 1.63, 1.6400000000000001, 1.65, 1.6600000000000001, 1.67]
n = len(xx)
mid = n//2
n, mid, n - mid - 1 # последний элемент не включительно
(20, 10, 9)
x_mid = xx[len(xx)//2]
print( "Корень", x_mid, abs(mt.cos(x_mid)) )
Корень 1.58 0.009203543268808336
x = [i/1000 + 1 for i in range(0, 1010, 10)]
xx = [i for i in x if abs(mt.cos(i)) < 0.01 ]
xx
[1.5699999999999998, 1.58]
Есть встроенная функция sum, которая считает сумму элементов массива.
x_mean = sum(xx)/len(xx)
print( "Корень", x_mean, abs(mt.cos(x_mean)) )
Корень 1.575 0.0042036608246882635
Со строчками не работает
sum(['a', 'b'])
--------------------------------------------------------------------------- TypeError Traceback (most recent call last) <ipython-input-190-0ca1e4efb8fe> in <module> ----> 1 sum(['a', 'b']) TypeError: unsupported operand type(s) for +: 'int' and 'str'
Генераторы и списки можно обходить посредством готовой конструкции цикл, но вообще говоря можно и вручную. Механизм обхода следующий.
Обход генератора
r = range(10)
ir = iter(r)
type(ir)
range_iterator
next(ir)
0
next(ir)
1
ir = iter(r)
while True:
k=next(ir, None)
if k == None:
break
print(k)
0 1 2 3 4 5 6 7 8 9
ir = iter(r)
Обход списка
l = [-3, 2, 7, 9]
it = iter(l)
type(it)
list_iterator
next(it), next(it), next(it)
(-3, 2, 7)
it = iter(l)
while True:
k=next(ir, None)
if k == None:
break
print(k)
0 1 2 3 4 5 6 7 8 9