# Способы проверки того, что
# все элементы списка одинаковы:
# Способы расположены от “most pythonic”, к “least pythonic”
# и от менее эффективных, до более эффективных.
# Решение с len(set()) сразу приходит на ум, однако
# конструирование множества расходует как память, так и время.
# все элементы списка одинаковы:
>>> lst = ['a', 'a', 'a']
>>> len(set(lst)) == 1
True
>>> all(x == lst[0] for x in lst)
True
>>> lst.count(lst[0]) == len(lst)
True
# Способы расположены от “most pythonic”, к “least pythonic”
# и от менее эффективных, до более эффективных.
# Решение с len(set()) сразу приходит на ум, однако
# конструирование множества расходует как память, так и время.
Bare * asterisk
В Python 3 можно использовать оператор * в списках параметров функции, чтобы наверняка использовать keyword аргументы.
То есть, мы должны прямо указать именованые параметры в виде key=value.
#bareasterisk
В Python 3 можно использовать оператор * в списках параметров функции, чтобы наверняка использовать keyword аргументы.
>>> def f(a, b, *, c='x', d='y', e='z'):
... return 'Hello'
То есть, мы должны прямо указать именованые параметры в виде key=value.
>>> f(1, 2, 'p', 'q', 'v')
TypeError:
"f() takes 2 positional arguments but 5 were given"
>>> f(1, 2, c='p', d='q',e='v')
'Hello’
#bareasterisk
Dict.
Пара коротких заметок по поводу словарей.
📌 Для того, чтобы взять “срез” словаря, можно поступить так:
📌 Для того, чтобы сложить два словаря:
P.S. Если будете копировать, поправьте кавычки. Телеграм их исправляет на нечитаемые python-ом.
#dict
Пара коротких заметок по поводу словарей.
📌 Для того, чтобы взять “срез” словаря, можно поступить так:
import itertools
m_dict = {‘1’:’1’, ‘2’:’2’, ‘3’:’3’, ‘4’:’4’, ‘5’:’5’}
m_dict = dict(itertools.islice(m_dict.items(), 3))
Out[0]: {‘1’:’1’, ‘2’:’2’, ‘3’:’3’}📌 Для того, чтобы сложить два словаря:
m_dict1 = {‘1’:’1’, ‘2’:’2’}
m_dict2 = {‘3’:’3’, ‘4’:’4’}
m_dict = dict(m_dict1, **m_dict2)Out[0]: {‘1’:’1’, ‘2’:’2’, ‘3’:’3’, ‘4’:’4’}P.S. Если будете копировать, поправьте кавычки. Телеграм их исправляет на нечитаемые python-ом.
#dict
Memoization.
➖Это способ оптимизации, при котором сохраняется результат выполнения функции и этот результат используется при следующем вызове.
Возьмем рекурсивную реализацию нахождения числа Фибоначчи и посмотрим на время выполнения.
➖При увеличении числа, время работы алгоритма будет очень быстро расти, плюс возможна ошибка RecursionError.
➖Для оптимизации подобного алгоритма хорошо подходит метод мемоизации, то есть сохранение и повторное использования ранее вычисленных значений.
В следующем посте разберем декоратор
➖Это способ оптимизации, при котором сохраняется результат выполнения функции и этот результат используется при следующем вызове.
Возьмем рекурсивную реализацию нахождения числа Фибоначчи и посмотрим на время выполнения.
@clock
def fib(n):
if n < 2:
return n
return fib(n-2) + fib(n-1)
print('fib(20) =', fib(20))
Out [0]: [0.22741317749023438s] fib(20) -> 6765
➖При увеличении числа, время работы алгоритма будет очень быстро расти, плюс возможна ошибка RecursionError.
➖Для оптимизации подобного алгоритма хорошо подходит метод мемоизации, то есть сохранение и повторное использования ранее вычисленных значений.
_fib_cache = {1: 1, 2: 1} # ключ - номер числа, значение - число Фибоначчи
@clock
def mem_fib(n):
result = _fib_cache.get(n)
if result is None:
result = mem_fib(n-2) + mem_fib(n-1)
_fib_cache[n] = result
return result
print('mem_fib(200) =', mem_fib(200))Out [0]: [0.011016845703125s] mem_fib(200) -> 280571172992510140037611932413038677189525
В следующем посте разберем декоратор
@clock, а также декорирование самой мемоизации.Memoization part 2.
Декоратор clock выглядит так:
Засекаем время выполнения нашей функции, а дальше просто выводим это в красивый принт. Не забудьте импортировать модуль time.
Для memoize напишем следующую функцию:
Или через лямбду:
Таким образом:
Декоратор clock выглядит так:
def clock(func):
def clocked(*args, **kwargs):
t0 = time.time() # начальное время
result = func(*args, **kwargs)
elapsed = time.time() - t0 # конечное время
arg_1st = []
if args:
arg_1st.append(', '.join(repr(arg) for arg in args))
if kwargs:
pairs = ['%s=%r' % (k, w) for k, w in sorted(kwargs.items())]
arg_1st.append(', '.join(pairs))
arg_str = ', '.join(arg_1st)
print(f'[{elapsed}s] {func.__name__}({arg_str}) -> {result}')
return result
return clocked
Засекаем время выполнения нашей функции, а дальше просто выводим это в красивый принт. Не забудьте импортировать модуль time.
Для memoize напишем следующую функцию:
def memoize(f):
cache = {}
def decorate(*args):
if args in cache:
return cache[args]
else:
cache[args] = f(*args)
return cache[args]
return decorate
Или через лямбду:
def memoize(f):
cache = {}
return lambda *args: cache[args] if args in cache else cache.update({args: f(*args)}) or cache[args]
Таким образом:
@memoize
@clock
def fib(n):
if n < 2:
return n
return fib(n-2) + fib(n-1)
print('fib(200) =', fib(200))
Out [0]: [0.0035719871520996094s] fib(200) -> 280571172992510140037611932413038677189525
Memoization part 3.
И напоследок, в стандартной библиотеке functools уже отлично реализован подобный декоратор, который называется lru_cache.
LRU расшифровывается как Least Recently Used.
lru_cache имеет два необязательных аргумента:
📌 maxsize — это количество хранимых результатов.
📌 typed — при равном true, например, значения 1 и 1.0 будут считаться разными (поскольку это разные типы).
📎 Мемоизация довольно простая и эффективная практика. А благодаря functools.lru_cache, ей удобно пользоваться в Python.
#lru #memoization
И напоследок, в стандартной библиотеке functools уже отлично реализован подобный декоратор, который называется lru_cache.
LRU расшифровывается как Least Recently Used.
from functools import lru_cache
@clock
@lru_cache()
def fib(n):
if n < 2:
return n
return fib(n-2) + fib(n-1)
print('fib(20) =', fib(20))
lru_cache имеет два необязательных аргумента:
📌 maxsize — это количество хранимых результатов.
📌 typed — при равном true, например, значения 1 и 1.0 будут считаться разными (поскольку это разные типы).
📎 Мемоизация довольно простая и эффективная практика. А благодаря functools.lru_cache, ей удобно пользоваться в Python.
#lru #memoization
Currying.
Теперь о каррировании. Каррирование (от англ. currying, иногда — карринг) — преобразование функции от многих аргументов в набор функций, каждая из которых является функцией от одного аргумента
Зачем нужно каррирование
📌С каррированием можно создавать краткие и лаконичные функции, подходящие для многоразового использования.
📌Эти функции используются в качестве чистых и пригодных для тестирования логических единиц при создании сложных с точки зрения логики частей программ.
В самом простейшем случае можно реализовать каррирование с помощью лямбда-функций.
Создадим простую функцию greet, которая принимает в виде аргументов приветствие и имя.
Небольшое улучшение позволит нам создать новую функцию для любого приветствия и передать этой функции имя.
Сделать это можно с любым числом аргументов.
#currying
Теперь о каррировании. Каррирование (от англ. currying, иногда — карринг) — преобразование функции от многих аргументов в набор функций, каждая из которых является функцией от одного аргумента
Зачем нужно каррирование
📌С каррированием можно создавать краткие и лаконичные функции, подходящие для многоразового использования.
📌Эти функции используются в качестве чистых и пригодных для тестирования логических единиц при создании сложных с точки зрения логики частей программ.
В самом простейшем случае можно реализовать каррирование с помощью лямбда-функций.
f = lambda y: lambda x: x + y
print(f(2)(2))
Out [0]: 4
Создадим простую функцию greet, которая принимает в виде аргументов приветствие и имя.
def greet(greeting, name):
print(greeting + ', ' + name)
greet('Hello', 'Nameless')
Небольшое улучшение позволит нам создать новую функцию для любого приветствия и передать этой функции имя.
def greet_curried(greeting):
def greet(name):
print(greeting + ', ' + name)
return greet
greet_hello = greet_curried('Hello')
greet_hello('German')
greet_hello('Ivan')
# или напрямую greet_curried
greet_curried('Hi')('Roma')
Сделать это можно с любым числом аргументов.
def greet_deeply_curried(greeting):
def w_separator(separator):
def w_emphasis(emphasis):
def w_name(name):
print(greeting + separator + name + emphasis)
return w_name
return w_emphasis
return w_separator
greet = greet_deeply_curried("Hello")("...")(".")
greet('German')
greet('Ivan')
#currying
Частичное применение (partial application).
Предоставление функции с меньшим количеством аргументов, чем она ожидает, называется частичным применением функций.
📎Другими словами, это функция, которая принимает функцию с несколькими параметрами и возвращает функцию с меньшим количеством параметров.
📎Частичное применение преобразует функцию от n аргументов в (n-m), а карринг, в свою очередь, создает n функций с одним аргументом.
Такая возможность есть у Python в стандартной библиотеке functools, функция называется partial.
#partial
Предоставление функции с меньшим количеством аргументов, чем она ожидает, называется частичным применением функций.
📎Другими словами, это функция, которая принимает функцию с несколькими параметрами и возвращает функцию с меньшим количеством параметров.
📎Частичное применение преобразует функцию от n аргументов в (n-m), а карринг, в свою очередь, создает n функций с одним аргументом.
Такая возможность есть у Python в стандартной библиотеке functools, функция называется partial.
from functools import partial
def greet(greeting, separator, emphasis, name):
print(greeting + separator + name + emphasis)
newfunc = partial(greet, greeting='Hello', separator=',', emphasis='.')
newfunc(name='German')
newfunc(name='Ivan')
newfunc2 = partial(greet, greeting='Hello', emphasis='.')
newfunc2(name='German', separator='...')
newfunc2(name='Ivan', separator='..')
#partial
Для тех, кто еще не видел, я написал статью о pandas для новичков. Тут все что нужно, для того чтобы начать работать с Series и DataFrame.
https://telegra.ph/Pandas-for-pussies-08-05
https://telegra.ph/Pandas-for-pussies-08-05
Telegraph
Pandas for beginners.
На сегодняшний день, пакет Pandas это самый важный инструмент во всем, что касается анализа данных. Многие аналитики и data scientis'ы пользуются этим пакетом. Первые шаги в Pandas
Первый шаг к тому, чтобы заниматься анализом данных - изучить библиотеку Pandas для Python. Вот небольшая статья, которая поможет начать изучение. В ней рассказывается о различных способах создания датафреймов в Pandas.
Автор статьи также ведет канал @datalytx, в котором регулярно размещаются полезные ссылки по анализу данных и автоматизации обработки данных с помощью Python.
http://bit.ly/2KutV0B
Автор статьи также ведет канал @datalytx, в котором регулярно размещаются полезные ссылки по анализу данных и автоматизации обработки данных с помощью Python.
http://bit.ly/2KutV0B
Medium
Миллион способов создать датафрейм
Всем привет, я Алексей Макаров, и я аналитик. Ещё я веду блог Datalytcs и одноименный канал @datalytx в Телеграме. Там я делюсь всякими…
Чай из itertools
Если вы читали предыдущие посты про итераторы, то примерно представляете как они работают (если нет, ищите по тегу #generators). Итератор обычно выдает значения по одному (с помощью метода
📌tee принимает два аргумента: исходный итератор и количество новых итераторов, на которые разделится исходный. А возвращает он кортеж из новых итераторов.
Вывод:
Видно, что каждый из полученных итераторов по сути является независимой копией исходного get_iter.
Несколько замечаний:
📌Не следует пытаться итерировать исходный get_iter, иначе производные итераторы могут потерять некоторые значения.
📌tee хранит в памяти извлеченные элементы, чтобы остальные потребители могли их получить, даже если исходный итератор уже сместился. Поэтому, если элементов много либо они большие, это может серьезно повлиять на расход памяти.
#tee #iterators
Если вы читали предыдущие посты про итераторы, то примерно представляете как они работают (если нет, ищите по тегу #generators). Итератор обычно выдает значения по одному (с помощью метода
__next__, например). Это означает, что получать значения из итератора может только один потребитель. Однако, это можно исправить.📌tee принимает два аргумента: исходный итератор и количество новых итераторов, на которые разделится исходный. А возвращает он кортеж из новых итераторов.
from itertools import tee
def get_iter():
for i in range(5):
yield i
one, two, three = tee(get_iter(), 3)
print(f'next is {next(one)}')
print(f'next is {next(two)}')
for item in three:
print(f'next is {item}')
Вывод:
next is 0
next is 0
next is 0
next is 1
next is 2
next is 3
next is 4
Видно, что каждый из полученных итераторов по сути является независимой копией исходного get_iter.
Несколько замечаний:
📌Не следует пытаться итерировать исходный get_iter, иначе производные итераторы могут потерять некоторые значения.
📌tee хранит в памяти извлеченные элементы, чтобы остальные потребители могли их получить, даже если исходный итератор уже сместился. Поэтому, если элементов много либо они большие, это может серьезно повлиять на расход памяти.
#tee #iterators
Немного новостей 🗒
📌Сейчас мы плотно заняты разработкой обучающего курса о создании ботов в телеграме. Что там вообще будет? А будет там много информации о самой библиотеке pyTelegramBotAPI, об обработчиках, о клавиатурах, о базах данных конечно и о веб хуках. Лично от меня — базы данных, платежки, встраивание платежек в бота.
📌Мы планируем продавать данный курс всем заинтересованным в этом людям. Вырученные деньги пойдут на развитие канала и закупы рекламы, поскольку я уже давно этим не занимался, а надо бы. Цена не будет слишком высокой. Это будет самое оно для тех, у кого давно есть идея создания собственного бота, но с реализацией напряг.
📌Кроме того, потихоньку осваиваю data science дальше, и изучаю нейросети. Нашел для вас отличную статью (не реклама, статья правда отличная) по машинному обучению. В планах сейчас освоение нейронок на хорошем уровне + создание своего приложения.
#news
📌Сейчас мы плотно заняты разработкой обучающего курса о создании ботов в телеграме. Что там вообще будет? А будет там много информации о самой библиотеке pyTelegramBotAPI, об обработчиках, о клавиатурах, о базах данных конечно и о веб хуках. Лично от меня — базы данных, платежки, встраивание платежек в бота.
📌Мы планируем продавать данный курс всем заинтересованным в этом людям. Вырученные деньги пойдут на развитие канала и закупы рекламы, поскольку я уже давно этим не занимался, а надо бы. Цена не будет слишком высокой. Это будет самое оно для тех, у кого давно есть идея создания собственного бота, но с реализацией напряг.
📌Кроме того, потихоньку осваиваю data science дальше, и изучаю нейросети. Нашел для вас отличную статью (не реклама, статья правда отличная) по машинному обучению. В планах сейчас освоение нейронок на хорошем уровне + создание своего приложения.
#news
Замыкания с поздним связыванием.
Один из распространенных источников путаницы в Python — способ связывания переменных в замыканиях (closures).
Например, вы пишите:
Что вы ожидаете:
Что происходит на самом деле:
Создаются пять функций, и все они умножают x на 4. Почему?
📌В языке Python замыкания имеют позднее связывание
📌Значения переменных, использованных в замыканиях, определяются в момент вызова внутренней функции
🔎В нашем примере, когда вызывается любая из возвращаемых функций, значение переменной i определяется с помощью окружающей области видимости в момент вызова. К этому моменту цикл завершает свою работу и i получает итоговое значение равное четырем.
#closures
Один из распространенных источников путаницы в Python — способ связывания переменных в замыканиях (closures).
Например, вы пишите:
def create_multipliers():
return [lambda x: i * x for i in range(5)]
for multiplier in create_multipliers():
print(multiplier(2), end=" ... ")
print()
Что вы ожидаете:
Out [0]: 0 … 2 … 4 … 6 … 8 …
Что происходит на самом деле:
Out [0]: 8 … 8 … 8 … 8 … 8 …
Создаются пять функций, и все они умножают x на 4. Почему?
📌В языке Python замыкания имеют позднее связывание
📌Значения переменных, использованных в замыканиях, определяются в момент вызова внутренней функции
🔎В нашем примере, когда вызывается любая из возвращаемых функций, значение переменной i определяется с помощью окружающей области видимости в момент вызова. К этому моменту цикл завершает свою работу и i получает итоговое значение равное четырем.
#closures
Как же тогда написать правильно? А вот об этом уже в следующий раз.
Если вас не тянет сейчас изучать все эти хитрости языка Python, а грядущая учеба кажется дерьмом, то напоминаю что у нас есть отличный авторский курс по ботам, который создал я и мой коллега.
Мы в теме ботов уже давно, если кто-то помнит наш бот по ставкам на футбольные матчи (сейчас бот в стадии обновления, парсеры переписаны с нуля и без использования splinter, который дико тормозил и нагружал систему).
Курс по ботам включает в себя работу с базами данных, с веб хуками и платежной системой QIWI. Он не требует каких-то особенных знаний Python и рассчитан преимущественно на новичков. Для записи пишите в бота @bots_course_bot
P.S. На следующей неделе запланировано поднятие цен, так что поспешите.
Если вас не тянет сейчас изучать все эти хитрости языка Python, а грядущая учеба кажется дерьмом, то напоминаю что у нас есть отличный авторский курс по ботам, который создал я и мой коллега.
Мы в теме ботов уже давно, если кто-то помнит наш бот по ставкам на футбольные матчи (сейчас бот в стадии обновления, парсеры переписаны с нуля и без использования splinter, который дико тормозил и нагружал систему).
Курс по ботам включает в себя работу с базами данных, с веб хуками и платежной системой QIWI. Он не требует каких-то особенных знаний Python и рассчитан преимущественно на новичков. Для записи пишите в бота @bots_course_bot
P.S. На следующей неделе запланировано поднятие цен, так что поспешите.
For masochists only.
А как вы относитесь к математике? Знакомы ли с векторным-тензорным анализом? Удовлетворяет ли вас институтский/школьный курс, или ничего вообще непонятно? Хотелось бы вам видеть больше математики на канале, даже не применительно только к языку Python?
Я считаю что роль математики в нашей жизни очень сильно недооценена. Напишите ваше мнение в комментарии, давайте обсудим это.
А как вы относитесь к математике? Знакомы ли с векторным-тензорным анализом? Удовлетворяет ли вас институтский/школьный курс, или ничего вообще непонятно? Хотелось бы вам видеть больше математики на канале, даже не применительно только к языку Python?
Я считаю что роль математики в нашей жизни очень сильно недооценена. Напишите ваше мнение в комментарии, давайте обсудим это.
Замыкания с поздним связыванием.
Недавно мы выяснили как работает позднее связывание в замыканиях в Python. Теперь попробуем устранить проблему, которая возникала при создании замыкания.
Наиболее общее решение, возможно, станет костылем. Из-за поведения Python при определении аргументов по умолчанию для функций, вы можете создать замыкание, которое немедленно связывается со своими аргументами про помощи аргумента по умолчанию:
Либо воспользоваться functools.partial():
В таком случае,
#closures
Недавно мы выяснили как работает позднее связывание в замыканиях в Python. Теперь попробуем устранить проблему, которая возникала при создании замыкания.
Наиболее общее решение, возможно, станет костылем. Из-за поведения Python при определении аргументов по умолчанию для функций, вы можете создать замыкание, которое немедленно связывается со своими аргументами про помощи аргумента по умолчанию:
def create_multipliers():
return [lambda x, i=i : i * x for i in range(5)]
Либо воспользоваться functools.partial():
from functools import partial
from operator import mul
def create_multipliers():
return [partial(mul, i) for i in range(5)]
В таком случае,
Out [0]: 0 … 2 … 4 … 6 … 8 …#closures
Математика на Python
Python можно и нужно использовать для математических или научных вычислений. Как его можно использовать? Узнаете в моей статье.
#статья #математика
Python можно и нужно использовать для математических или научных вычислений. Как его можно использовать? Узнаете в моей статье.
#статья #математика
Telegraph
Математические вычисления в Python
Вместо введения. В течение нескольких последних лет экосистема языка Python стремительно развивалась. С помощью Python можно успешно разрабатывать не только веб-приложения и системные утилиты. С его помощью можно работать с нейронными сетями, компьютерным…
5 способов форматирования строк
1. Конкатенация.
Грубый способ форматирования, в котором мы просто склеиваем несколько строк с помощью операции сложения.
2. %-форматирование.
Самый популярный способ, который перешел в Python из языка С. Передавать значения в строку можно через списки и кортежи , а также и с помощью словаря. Во втором случае значения помещаются не по позиции, а в соответствии с именами.
3. Template-строки.
Этот способ появился в Python 2.4, как замена %-форматированию (PEP 292), но популярным так и не стал. Поддерживает передачу значений по имени и использует $-синтаксис как в PHP.
4. Форматирование с помощью метода format().
Этот способ появился в Python 3 в качестве замены %-форматированию. Он также поддерживает передачу значений по позиции и по имени.
5. f-строки.
Форматирование, которое появилось в Python 3.6 (PEP 498). Этот способ похож на форматирование с помощью метода format(), но гибче, читабельней и быстрей.
#string
1. Конкатенация.
Грубый способ форматирования, в котором мы просто склеиваем несколько строк с помощью операции сложения.
name = "Дмитрий"
age = 25
print("Меня зовут " + name + ". Мне " + str(age) + " лет.")
# Output: Меня зовут Дмитрий. Мне 25 лет.
2. %-форматирование.
Самый популярный способ, который перешел в Python из языка С. Передавать значения в строку можно через списки и кортежи , а также и с помощью словаря. Во втором случае значения помещаются не по позиции, а в соответствии с именами.
name = "Дмитрий"
age = 25
print("Меня зовут %s. Мне %d лет." % (name, age))
# Output: Меня зовут Дмитрий. Мне 25 лет.
print("Меня зовут %(name)s. Мне %(age)d лет." % {"name": name, "age": age})
# Output: Меня зовут Дмитрий. Мне 25 лет.
3. Template-строки.
Этот способ появился в Python 2.4, как замена %-форматированию (PEP 292), но популярным так и не стал. Поддерживает передачу значений по имени и использует $-синтаксис как в PHP.
from string import Template
name = "Дмитрий"
age = 25
s = Template('Меня зовут $name. Мне $age лет.')
print(s.substitute(name=name, age=age))
# Output: Меня зовут Дмитрий. Мне 25 лет.
4. Форматирование с помощью метода format().
Этот способ появился в Python 3 в качестве замены %-форматированию. Он также поддерживает передачу значений по позиции и по имени.
name = "Дмитрий"
age = 25
print("Меня зовут {}. Мне {} лет.".format(name, age)
# Output: Меня зовут Дмитрий. Мне 25 лет.
print("Меня зовут {name} Мне {age} лет.".format(age=age, name=name)
# Output: Меня зовут Дмитрий. Мне 25 лет.
5. f-строки.
Форматирование, которое появилось в Python 3.6 (PEP 498). Этот способ похож на форматирование с помощью метода format(), но гибче, читабельней и быстрей.
name = "Дмитрий"
age = 25
print(f"Меня зовут {name} Мне {age} лет.")
# Output: Меня зовут Дмитрий. Мне 25 лет.
#string