Математический практикум по Питону.
На базе задачи построения графиков, в частности, эмитентов, вводится функциональный подход в рамках (Python версии 3.xx). Рассматриваются map filter и reduce, а также библиотека csv. Далее изучаются более продвинутые функции функционального программирования из базовых модулей itertools, functools и operator. В частности, повторы (count, ...), комбинации (product, ...), обработка (chain, starmap, dropwhile, ...) частичное вычисление (partial и attrgetter). Ключевые слова: map, filter, reduce, lambda, matplotlib, pyplot, xlim, xticks, csv и plot.
Это предварительная версия! Любые замечания приветствуются.
Рассмотрим как можно обрабатывать список элементов. Замечу, что существуют три главных действия на список элементов.
map
Возьмем список неких чисел.
l = [4, 25, 9, 16]
import math as mt
i = 0
for i in range(len(l)):
l[i] = mt.sqrt(l[i])
l
[2.0, 5.0, 3.0, 4.0]
Можно короче использую языковые конструкции.
l = [4, 25, 9, 16]
# Применим функцию np.sqrt для всех элиментов списка l.
map( mt.sqrt, l) # Первый аргумент функция, второй -- список.
<map at 0x7fc8582db860>
Пока результат не вывелся.
q = map( mt.sqrt, l)
q # Посмотрим содержимое.
<map at 0x7fc8582dbda0>
# Проверяем тип.
type( q ) # Map есть map.
map
Map это объект ленивого действие (~генератор). Нужно чтобы числа им были сгенерированы.
# Для этого создадим объект список с его помощью.
list( q )
[2.0, 5.0, 3.0, 4.0]
Ну или
# Нужно заново, так как он уже отработал.
q = map( mt.sqrt, l)
for i in q:
print(i, sep = " ", end="")
2.05.03.04.0
q = map( mt.sqrt, l) # Создали генератор по списку l.
l.append(81) # Добавили в список l элемент.
list(q) # Он был учтен,
# т.е. генератор актуальный список.
[2.0, 5.0, 3.0, 4.0, 9.0]
# Приведем другой пример.
ll = [mt.pi/2, mt.pi, mt.pi/4]
list( map( mt.sin, ll ) ) # Взяли синус от каждого элемента
[1.0, 1.2246467991473532e-16, 0.7071067811865475]
Преобразование
Как задать собственное преобразование. Для простых преобразований в питоне есть лямбда функции.
Данная конструкция задается следующим образом:
lambdaсписок аргументов/параметров : действие/значение.
lambda x: x*2 # Умножаем число на 2.
lambda x, y: x**y # Возводим первое чило в степень второго.
# Тип имеет функции.
<function __main__.<lambda>(x, y)>
# Для их применения например можно сохранить в переменну.
dbl = lambda x: x*2
mypow = lambda x, y: x**y
dbl, mypow
(<function __main__.<lambda>(x)>, <function __main__.<lambda>(x, y)>)
type( dbl ), type( mypow )
(function, function)
# Применим преоьразование к числам.
dbl( 2), dbl( 2.5 ), mypow( 2, 3 )
(4, 5.0, 8)
l # Вспомним содержимое списка.
[4, 25, 9, 16, 81]
i = 0
ll = l.copy()
for i in range(len(ll)):
ll[i] = dbl(ll[i])
ll
[8, 50, 18, 32, 162]
g = []
for e in l:
g.append( dbl( e ) )
g
[8, 50, 18, 32, 162]
# Применим к каждому элемента списка преобразование,
q = map( dbl, l) # умножение на два.
q
<map at 0x7fc858286710>
# Построим список по q.
list( q )
[8, 50, 18, 32, 162]
# Можно в явном виде.
q = map( lambda x: x*2, l)
q
<map at 0x7fc8582865f8>
list( q )
[8, 50, 18, 32, 162]
list( map( lambda x: x*2, l) )
[8, 50, 18, 32, 162]
# Можно так. Выводятся элементы.
list( map( print, l) )
# Список портится.
4 25 9 16 81
[None, None, None, None, None]
Упр. Для квадратного уравнения расписать значения в точках (например корнях).
Частично заданые аргументы
# Все аргументы нужно указывать.
list( map( mypow(,0.5), l) )
# list( map( np.power(,0.5), l) )
# Будет ошибка.
File "<ipython-input-25-482acafcca92>", line 2 list( map( mypow(,0.5), l) ) ^ SyntaxError: invalid syntax
# Нужно так: lambda от labmda.
list( map( lambda x: mypow(x, 0.5), l) )
#list( map( lambda x: np.power(x,0.5), l) )
[2.0, 5.0, 3.0, 4.0, 9.0]
filter
Используется для фильтрации (как сито) элементов списка. После обработки остаются не все элементы списка. Остаются только те для которые дают истину (для предиката).
# Возвращает истину тогда и только тогдв число нечетное.
odd = lambda x: x%2 == 1
odd(1), odd(4), odd(5.1)
(True, False, False)
list(map(odd, [1,4,6,5,8,9,11]))
[True, False, False, True, False, True, True]
ll = [1,4,6,5,8,9,11]
g = []
for e in ll:
if not odd(e):
continue
g.append(e)
g
[1, 5, 9, 11]
list([e for e in ll if odd(e)])
[1, 5, 9, 11]
q = filter( odd, ll)
q # Тоже возвращает не сам список, а генератор.
<filter at 0x7fc8582b0518>
# Формируем числа используя генератор.
list( q ) # От списка останется только те элементы
# на которых была истина: нечетные.
# т.е. остались нечетные эелементы.
[1, 5, 9, 11]
list(filter( odd, ll))
[1, 5, 9, 11]
Так нельзя
list(filter( not odd, ll))
--------------------------------------------------------------------------- TypeError Traceback (most recent call last) <ipython-input-36-025b18db9b54> in <module> ----> 1 list(filter( not odd, ll)) TypeError: 'bool' object is not callable
ll
[1, 4, 6, 5, 8, 9, 11]
список студентов
stud = []
stud.append( ['муж', 'Максим'] )
stud.append( ['жен', 'Лена'] )
stud.append( ['жен', 'Катя'] )
stud.append( ['муж', 'Дима'] )
stud.append( ['муж', 'Саша'] )
stud.append( ['жен', 'Яна'] )
stud
[['муж', 'Максим'], ['жен', 'Лена'], ['жен', 'Катя'], ['муж', 'Дима'], ['муж', 'Саша'], ['жен', 'Яна']]
stud[2]
['жен', 'Катя']
print( 'идекс 0:', stud[2][0], 'и индекс 1:', stud[2][1] )
идекс 0: жен и индекс 1: Катя
# Тогда можно проверить что на нулевом индексе значение 'муж'
male = lambda x: x[0] == 'муж'
print(stud[2], 'мужчина? Ответ: ', male( stud[2] ) )
print(stud[3], 'мужчина? Ответ: ', male( stud[3] ) )
['жен', 'Катя'] мужчина? Ответ: False ['муж', 'Дима'] мужчина? Ответ: True
men = list( filter(male, stud) )
men
[['муж', 'Максим'], ['муж', 'Дима'], ['муж', 'Саша']]
men[1] # Такая же пока структура.
['муж', 'Дима']
list( map( lambda x: x[1], men) ) # Извлекаем имя.
['Максим', 'Дима', 'Саша']
list( map( lambda x: x[1], stud) ) # Извлекаем имя.
['Максим', 'Лена', 'Катя', 'Дима', 'Саша', 'Яна']
Упр. Оставить тех студентов у которых имя завершается на букву а.
От двух аргументов
буквы = ['a', 'b', 'c', 'd']
цифры = [1, 2, 3, 4]
симво = ['!', '@', '#', '$']
len(буквы), len(цифры), len(симво)
(4, 4, 4)
list(zip(буквы, цифры, симво))
[('a', 1, '!'), ('b', 2, '@'), ('c', 3, '#'), ('d', 4, '$')]
aa = [1, 2, -1, 3]
bb = [3, 2, 2, 3]
ab = zip( aa, bb)
list(ab)
[(1, 3), (2, 2), (-1, 2), (3, 3)]
list( map( lambda ar: pow( ar[0], ar[1]), zip( aa, bb) ) )
[1, 4, 1, 27]
reduce
Другим действием является редукция, т.е. сведение списка к некому значению.
from functools import reduce
mac = lambda acc, x: acc + 2*x # acc аккумулирует значение. Правило ассоциативно.
reduce( mac, [-1,2,3]) # (-1 + 2*(2)) + 2*(3) есть 9. Ясно что ассоциативно.
9
mac2 = lambda acc, x: 2*acc + x # неассоциатовно
reduce( mac2, [ -2, 2, 3] ) # 2*(2*(-2) + 2) + 3 есть -1.
-1
2*(2*(-2) + 2) + 3
-1
sum( [-1, 2, 3] )
4
Условно,
pp = [1, 2, 3, 2, 5]
reduce( lambda acc, x: acc*x, pp )
60
а можно было бы
logs = list( map( mt.log, pp) )
logs
[0.0, 0.6931471805599453, 1.0986122886681098, 0.6931471805599453, 1.6094379124341003]
v = mt.exp( sum(logs) )
v, round(v)
(59.999999999999986, 60)
Значения совпали
магия
Будем строить функцию по-точечно, т.е. построем значение в каждой из выбранных точек и соеденим соседнии прямой. Для начала сгенерируем точки в которых будет вычислена функция.
x_10 = list( range(0, 10, 1) )
# Выполним преобразование списка чисел 0 до 9
list( map( lambda x: x/2 - 2, x_10 ) )
# Получим список чисел с шагом в 0.5 от -2 до 2.5.
[-2.0, -1.5, -1.0, -0.5, 0.0, 0.5, 1.0, 1.5, 2.0, 2.5]
# Теперь возьмем список побольше
x_30 = list( range(0, 30, 1) )
len( x_30 )
30
#Сгенерируем именно равномерный на набор точек.
x = list( map( lambda x: x/2 - 5, x_30 ) )
# список от -5 до 9.5 с шагом в 0.5.
# Пишем выражение, которое ествественно будет вычислено в каждой точке,
f = lambda x:x*x - 2*x +3 # т.е. по-элементно для списка x.
y = list( map( f, x) )
len(x), len(y) # Видим что длины совпадают.
(30, 30)
# Значение в точке -2 равно 11.
x[6], y[6] # (-2)*(-2) - 2(-2) + 3 = 4 + 4 + 3 = 11
(-2.0, 11.0)
type(x), type(y)
(list, list)
import matplotlib.pyplot as plt
# Можно рисовать несколько графиков на одном чертеже:
y2 = list( map( lambda x: 10*mt.sin( x ) + 25, x) )
# сначала тройка первого графика, потом второго.
plt.plot( x, y, 'g.-', x, y2, 'b*--');
# Ествественно, что значения можно считать "налету":
plt.plot( x, list( map( lambda x: mt.sin(x), x) ), 'g.-')
plt.plot( x, list( map( lambda x: x*x/100, x) ), 'b*--')
plt.legend( ['sin', 'x^2'] ); # Добавим и легенду.
Ввиду того, что количество точек по которым строилась кривая было небольшим, синусойда получилась угловатой.
plt.plot( x, y, 'g.-')
plt.xticks( [-2, 0.5, 2, 5] ) # Задаем отсчеты вдоль оси абсцисс.
plt.xlim(-4, 8) # Зданаем границы дипазона для оси абсцисс.
(-4.0, 8.0)
plt.plot( x, list( map( lambda x: mt.exp(x), x) ), 'g.-')
[<matplotlib.lines.Line2D at 0x7fc81704b748>]
plt.plot( x, list( map( lambda x: mt.exp(x), x) ), 'g.-')
plt.yscale( 'log' ) # Меняем шкалу на логарифмическую.
Берем откуда-то простой csv (comma seperated values) файл. Отмечу, что расширение у некго не обязано быть csv, оно может быть и txt.
Например с https://www.finam.ru/profile/moex-akcii/mechel/export/ Параметры можно менять: сменить эмитента (например, выбрать Газпром, Сбербанк и тому подобное), период (например, выбрать день). Промежуток времени пока лучше выбрать поменьше. Внимание, пока скачиваем файл без заголовка (убрать соответствующий флажок)! Символ ; в качестве разделителя.
Для считывания данных файлов потребуется библиотека csv.
import csv # Для считывания csv файлов.
#data = []
with open('MTLR_190101_190110.txt') as f:
data_rows = csv.reader( f )
data = list( data_rows )
data
[['MTLR;D;20190103;000000;73.8900000;74.4700000;73.0600000;73.1200000;391375'], ['MTLR;D;20190104;000000;73.3100000;74.8900000;73.2100000;73.6800000;462658'], ['MTLR;D;20190108;000000;74.4700000;74.8900000;73.5000000;73.7400000;406304'], ['MTLR;D;20190109;000000;74.0200000;74.6200000;73.8200000;73.9300000;651998'], ['MTLR;D;20190110;000000;73.9600000;74.7800000;73.9000000;74.4000000;358269']]
len(data)
5
data[1]
['MTLR;D;20190104;000000;73.3100000;74.8900000;73.2100000;73.6800000;462658']
Видно, что строчки из файла считались целиком, как текстовые строчки (обрати внимание на одинарные кавычки). Хотелось бы чтобы каждый столбец отделился от других столбцов. Для этого можно указать дополнительный параметр функции обработки csv файлов. Параметр delimiter, он указывает какой разделитель используется для отделения стобцов.
data = []
with open('MTLR_190101_190110.txt') as f:
data_rows = csv.reader( f, delimiter = ';' )
data = list( data_rows )
data
[['MTLR', 'D', '20190103', '000000', '73.8900000', '74.4700000', '73.0600000', '73.1200000', '391375'], ['MTLR', 'D', '20190104', '000000', '73.3100000', '74.8900000', '73.2100000', '73.6800000', '462658'], ['MTLR', 'D', '20190108', '000000', '74.4700000', '74.8900000', '73.5000000', '73.7400000', '406304'], ['MTLR', 'D', '20190109', '000000', '74.0200000', '74.6200000', '73.8200000', '73.9300000', '651998'], ['MTLR', 'D', '20190110', '000000', '73.9600000', '74.7800000', '73.9000000', '74.4000000', '358269']]
Теперь видно, что все стобцы считались по отедльности. Но каждый элемент по прежнему является стройчкой. Нужно для тех стобцов про кторые мы знаем наверняка выполнить явное пробразование из текста в число.
Ранее нам уже встречалось явное преобразование, когда мы преобразовывали истинность в число.
data[1]
['MTLR', 'D', '20190104', '000000', '73.3100000', '74.8900000', '73.2100000', '73.6800000', '462658']
float(data[1][4])
73.31
Нам должна быть известна структура входного файла. Точнее должно быть известно назначение столбцов. Для ранее скаченного файла она такая: TICKER, PER, DATE, TIME, OPEN, HIGH, LOW, CLOSE, VOL. Предпоследний столбец соответствует цене закрытия.
# Извлечение цены закрытия
get_close = lambda x: x[-2]
data[2]
['MTLR', 'D', '20190108', '000000', '74.4700000', '74.8900000', '73.5000000', '73.7400000', '406304']
get_close(data[2])
# Будет сторокой.
'73.7400000'
fromStr = lambda x: float(x)
fromStr( get_close(data[2]) )
73.74
close_str = list( map( get_close, data) )
close_str
['73.1200000', '73.6800000', '73.7400000', '73.9300000', '74.4000000']
close = list( map( fromStr, close_str) )
close
[73.12, 73.68, 73.74, 73.93, 74.4]
# В два прохода.
close_str = list( map( lambda x: x[-2], data) )
close = list( map( lambda x: float(x), close_str) )
close
[73.12, 73.68, 73.74, 73.93, 74.4]
# Или в один, сразу.
close = list( map( lambda x: float(x[-2]), data) )
close
[73.12, 73.68, 73.74, 73.93, 74.4]
Теперь все сработало и был считан столбец значений.
Теперь возьмем файл побольше и построим график.
data = []
with open( 'MTLR_180101_190110.txt' ) as f:
data_rows = csv.reader( f, delimiter = ';' )
data = list( data_rows )
close = list( map( lambda x: float(x[-2]), data) )
#close Не будем его выводить. Там много данных.
len( close ) # А именно столько.
259
close[10:20] # Посмотрим на кусочек данных.
[149.9, 147.0, 153.0, 154.3, 152.95, 150.0, 149.2, 145.2, 145.0, 146.05]
plt.plot( close ) # Рисуем график.
plt.ylabel( 'Цена рубли') # Название для оси y (оси ординат).
plt.xlabel( 'День начиная с 2018 г') # Название для оси x (оси абсцисс).
Text(0.5, 0, 'День начиная с 2018 г')
Упр. Нарисуй графики процентного изменения цены данного эмитента с начала периода. С легендой.
import itertools as it
До бесконечности.
for j in it.count(5):
print(j)
if j > 8:
break
5 6 7 8 9
ii = 0
for j in it.cycle(['Маша', 'Катя', 'Даша']):
print(f'{j} ', end='')
ii+=1
if ii>=8:
break
Маша Катя Даша Маша Катя Даша Маша Катя
for j in it.repeat('учиться', 3):
print(f'{j} ', end='')
учиться учиться учиться
То как отвечать в некоторых опросах:
for j in it.repeat('Нет', 5):
print(f'{j} ', end='')
Нет Нет Нет Нет Нет
for el in it.product( range(3), range(2)):
print(f'{el} ', end='')
(0, 0) (0, 1) (1, 0) (1, 1) (2, 0) (2, 1)
for x in range(3):
for y in range(2): # Подгоним печать под ту, что была
print(f'({x}, {y}) ', end='') # в прошлой ячейке.
(0, 0) (0, 1) (1, 0) (1, 1) (2, 0) (2, 1)
Варианты для выход на улицу
for el in it.product( ['рубашка', 'футболка'], ['броюки', 'шорты', 'джинсы']):
print(f'{el} ', end='')
('рубашка', 'броюки') ('рубашка', 'шорты') ('рубашка', 'джинсы') ('футболка', 'броюки') ('футболка', 'шорты') ('футболка', 'джинсы')
for perm in it.permutations( ['Даша', 'Оля', 'Маша'], 2 ):
print(f'{perm} ', end='')
('Даша', 'Оля') ('Даша', 'Маша') ('Оля', 'Даша') ('Оля', 'Маша') ('Маша', 'Даша') ('Маша', 'Оля')
for perm in it.combinations( ['Даша', 'Оля', 'Маша'], 2 ):
print(f'{perm} ', end='')
('Даша', 'Оля') ('Даша', 'Маша') ('Оля', 'Маша')
for perm in it.combinations_with_replacement( ['Даша', 'Оля', 'Маша'], 2 ):
print(f'{perm} ', end='')
('Даша', 'Даша') ('Даша', 'Оля') ('Даша', 'Маша') ('Оля', 'Оля') ('Оля', 'Маша') ('Маша', 'Маша')
Аккумулирование, частичные суммы.
for cs in it.accumulate([3,5,7]):
print(f'{cs} ', end='')
3 8 15
Конкатенация последовательностей.
for e in it.chain([0,1,2,3],['a','b','c'],['A','B','C'],['!','@','#']):
print(f'{e} ', end='')
0 1 2 3 a b c A B C ! @ #
Разбиение на группы. Должны быть отсортированы
for k, i in it.groupby(['Aня', 'Aня', 'Aня', 'Варя', 'Варя', 'Даша', 'Даша', 'Даша', 'Даша']):
#print(i)
print([j for j in i])
['Aня', 'Aня', 'Aня'] ['Варя', 'Варя'] ['Даша', 'Даша', 'Даша', 'Даша']
courses = [['Маша', 'Матан'], ['Аня', 'программирование'], ['Катя', 'теория Чисел'], ['Аня', 'Линейная алгебра'], ['Маша', 'Алгебра'] ]
getName = lambda i: i[0]
getName( courses[2])
'Катя'
courses.sort( key = getName )
courses
[['Аня', 'программирование'], ['Аня', 'Линейная алгебра'], ['Катя', 'теория Чисел'], ['Маша', 'Матан'], ['Маша', 'Алгебра']]
for k, i in it.groupby( courses, key = getName):
print( f'{k} сдала спецкурсы:' + ', '.join([j[1].lower().capitalize() for j in i]) )
Аня сдала спецкурсы:Программирование, Линейная алгебра Катя сдала спецкурсы:Теория чисел Маша сдала спецкурсы:Матан, Алгебра
Вызов многоаргументной функции
for v in it.starmap(pow, [[2, 5], [3, 2], [10, 3]]):
print(f'{v} ', end='')
32 9 1000
for v in it.starmap( lambda x, y: x+y, [[2, 5], [3, 2], [10, 3]]):
print(f'{v} ', end='')
7 5 13
l=[16, 25, 4]
list( it.starmap( pow, zip( l, it.repeat(0.5, len(l)) ) ) )
[4.0, 5.0, 2.0]
Последовательность
s = 'abcdefg12345678abcd'
for c in it.dropwhile( lambda x: x.isalpha(), s):
print(f'{c} ', end='')
1 2 3 4 5 6 7 8 a b c d
for c in it.takewhile( lambda x: x.isalpha(), s):
print(f'{c} ', end='')
a b c d e f g
for cc in it.takewhile( lambda x: x.isdigit(), it.dropwhile( lambda x: x.isalpha(), s)):
print(f'{cc} ', end='')
1 2 3 4 5 6 7 8
пронумеровать
# не запукать! list(it.zip_longest( s, it.count(0) ))
# Можно это
dat = it.zip_longest( s, it.count(0) )
dat
<itertools.zip_longest at 0x7fc816f69b88>
for cc in it.islice( dat, len(s)):
print(f'[{cc[1]}] = {cc[0]}, ', end='')
[0] = a, [1] = b, [2] = c, [3] = d, [4] = e, [5] = f, [6] = g, [7] = 1, [8] = 2, [9] = 3, [10] = 4, [11] = 5, [12] = 6, [13] = 7, [14] = 8, [15] = a, [16] = b, [17] = c, [18] = d,
оставим только числа
# В случае ложности предиката элемент остается.
for c in it.filterfalse( lambda x: x.isalpha(), s):
print(f'{c} ', end='')
1 2 3 4 5 6 7 8
Позволяет вырезать каждый n-ый
for n in it.compress( ['Маша', 'Аня', 'Катя', 'Даша', 'Лена'], map( lambda e: e%2, it.count(0) ) ):
print(f'{n} ', end='')
Аня Даша
len(close)
259
close[10:20]
[149.9, 147.0, 153.0, 154.3, 152.95, 150.0, 149.2, 145.2, 145.0, 146.05]
cur0 = it.islice(close, 0, 100)
cur1 = it.islice(close, 1, 101)
cur2 = it.islice(close, 2, 102)
cur3 = it.islice(close, 3, 103)
grp = it.zip_longest( cur0, cur1, cur2, cur3 )
Дублируем итератор.
itst, imin, imax = it.tee( grp, 3)
next(itst)
(155.75, 154.2, 154.5, 155.6)
Сдвигаются на один
next(itst)
(154.2, 154.5, 155.6, 154.7)
null = map( len, itst)
vmin = map( min, imin)
vmax = map( max, imax)
null, vmin, vmax
(<map at 0x7fc81f242ac8>, <map at 0x7fc81f242c18>, <map at 0x7fc81f242048>)
Тогда можно так
lens = list( null )
vvmin = list( vmin )
vvmax = list( vmax )
Лучше их обрабатывать в параллель.
vvmin[:10], vvmax[:10]
([154.2, 154.2, 154.5, 152.65, 152.65, 152.65, 150.65, 149.9, 147.0, 147.0], [155.75, 155.6, 155.6, 155.6, 155.0, 155.0, 154.95, 154.95, 154.0, 153.0])
plt.plot( close )
plt.plot( vvmin )
plt.plot( vvmax )
plt.xlim(0, 100)
plt.ylabel( 'Цена рубли')
plt.xlabel( 'День начиная с 2018 г')
Text(0.5, 0, 'День начиная с 2018 г')
matrx = [[1, 2, 3], [4, 5, 6]]
matrx
[[1, 2, 3], [4, 5, 6]]
Упр. Как транспонировать матрицу (список списков)? Использовать разрешено только что пройденные методы/приемы.
# Хотим:
[[1, 4], [2, 5], [3, 6]]
[[1, 4], [2, 5], [3, 6]]
import functools as ft
Возведение в степень
mt.pow(2,3)
8.0
ll
[1, 4, 6, 5, 8, 9, 11]
Хотим задать первый аргумент
Ранее делали так:
list( map( lambda x: mt.pow(2, x), ll) )
[2.0, 16.0, 64.0, 32.0, 256.0, 512.0, 2048.0]
А можно так используя встроенную функцию.
pow2 = ft.partial( mt.pow, 2)
list( map( pow2, ll ))
[2.0, 16.0, 64.0, 32.0, 256.0, 512.0, 2048.0]
А как явно задать второй?
qq = list( map( lambda x: ft.partial( mt.pow, x), ll ))
qq # список из функций
[functools.partial(<built-in function pow>, 1), functools.partial(<built-in function pow>, 4), functools.partial(<built-in function pow>, 6), functools.partial(<built-in function pow>, 5), functools.partial(<built-in function pow>, 8), functools.partial(<built-in function pow>, 9), functools.partial(<built-in function pow>, 11)]
list( map( lambda f: f(2), qq))
[1.0, 16.0, 36.0, 25.0, 64.0, 81.0, 121.0]
Печать
pnt = ft.partial( print, sep = ' ', end='')
pnt( 'числа:', 1, 2, '.' )
pnt( ' еще:', 3, 4, '.' )
числа: 1 2 . еще: 3 4 .
Обработка списка
isalpha = ft.partialmethod(str.isalpha)
isalpha
functools.partialmethod(<method 'isalpha' of 'str' objects>, , )
isalpha.func('abc'), isalpha.func('aa2')
(True, False)
isdigit = ft.partialmethod( str.isdigit )
isdigit
functools.partialmethod(<method 'isdigit' of 'str' objects>, , )
isdigit.func('123'), isdigit.func('aa2')
(True, False)
for cc in it.takewhile( isdigit.func, it.dropwhile( isalpha.func, s)):
print(f'{cc} ', end='')
1 2 3 4 5 6 7 8
import operator as op
Стандартные
op.add(2, 3), op.add('a', 'b')
(5, 'ab')
for v in it.starmap( op.add, [[2, 5], [3, 2], [10, 3]]):
print(f'{v} ', end='')
7 5 13
Атрибут
z = 1+2j
z
(1+2j)
z.real
1.0
zz = [ 1+2j, 3-2j, -1+1j]
real = op.attrgetter('real')
real(z)
1.0
list(map( real, zz))
[1.0, 3.0, -1.0]
[real(o) for o in zz]
[1.0, 3.0, -1.0]
конечно можно было бы
[o.real for o in zz]
[1.0, 3.0, -1.0]
или
list(map( lambda o: o.real, zz))
[1.0, 3.0, -1.0]
Скорее полезно если поля вводится
ff = input("введите атрибут")
fild = op.attrgetter( ff )
list(map( fild, zz))
[2.0, -2.0, 1.0]
stud[1]
['жен', 'Лена']
pol = op.itemgetter(0)
nam = op.itemgetter(1)
pol( stud[1] ), nam( stud[1] ),
('жен', 'Лена')
pols = map( pol, stud)
list( filter( ft.partial( op.eq, 'муж'), pols) )
['муж', 'муж', 'муж']
pols = map( pol, stud)
qpols = list( map( ft.partial( op.eq, 'муж'), pols) )
qpols
[True, False, False, True, True, False]
list( it.compress( stud, qpols))
[['муж', 'Максим'], ['муж', 'Дима'], ['муж', 'Саша']]
pols = map( pol, stud)
list( it.filterfalse( ft.partial( op.eq, 'муж'), pols ) )
['жен', 'жен', 'жен']
Упр. Написать ламбда функцию которая вычисляет значение квадратичной функции по заданным коэффициентам и точке. Потом применить частичную задачу аргументов для коэффициентов.