Hello World
رفتن به کانال در Telegram
Подписывается челик на канал, а он ему как раз 🎩 По рекламе: @my_little_trump
نمایش بیشتر2 456
مشترکین
اطلاعاتی وجود ندارد24 ساعت
اطلاعاتی وجود ندارد7 روز
اطلاعاتی وجود ندارد30 روز
آرشیو پست ها
2 456
Memoization part 3.
И напоследок, в стандартной библиотеке 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 #memoization2 456
Memoization part 2.
Декоратор 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
2 456
Memoization.
➖Это способ оптимизации, при котором сохраняется результат выполнения функции и этот результат используется при следующем вызове.
Возьмем рекурсивную реализацию нахождения числа Фибоначчи и посмотрим на время выполнения.
@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, а также декорирование самой мемоизации.2 456
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-ом.
#dict2 456
Bare * asterisk
В 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
2 456
# Способы проверки того, что
# все элементы списка одинаковы:
>>> 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()) сразу приходит на ум, однако # конструирование множества расходует как память, так и время.
2 456
Градиентный спуск.
Градиентный спуск — самый используемый алгоритм обучения, он применяется почти в каждой модели машинного обучения. Градиентный спуск — это, по сути, и есть то, как обучаются модели. Без ГС машинное обучение не было бы там, где сейчас. Метод градиентного спуска с некоторой модификацией широко используется для обучения персептрона и глубоких нейронных сетей, и известен как метод обратного распространения ошибки.
Что такое градиентный спуск.
Градиентный спуск — метод нахождения минимального значения функции многих переменных. Минимизация любой такой функции означает поиск самой глубокой впадины в этой функции. Поиск минимума в машинном обучении означает получение наименьшей возможной ошибки или повышение точности модели. Мы увеличиваем точность, перебирая набор учебных данных при настройке параметров нашей модели (весов и смещений).
Суть алгоритма – процесс получения наименьшего значения ошибки. Аналогично это можно рассматривать как спуск во впадину в попытке найти золото на дне ущелья (самое низкое значение ошибки).
Перейдем к практике.
Рассмотрим самый простейший случай применения градиентного спуска, а именно, поиск минимума заданной функции.
В одномерном случае, градиент функции (в проекции на выбранную ось) представяет собой обычную одномерную производную.
Возьмем функцию f(x) = x^4 - 3x^3 + 1, с производной f’(x) = 4x^3 - 9x^2.
Выберем начальную точку x0 = 6 (начальная точка может быть практически любой, за исключением концов отрезка, если мы рассматриваем нашу функцию на отрезке). Выберем размер шага gamma = 0.01 (шаг, с которым мы будем “скатываться” в ямку минимума). Если выбрать слишком большой шаг, можно проскочить минимум, а если слишком маленький, то в случае сложной функции с несколькими минимумами, можно оказаться в локальном минимуме вместо глобального.
Попробуйте поиграть с этими двумя параметрами.
Где же код?
А вот он.
def get_min(x, df, gamma):
eps = 1e-6
max_iters = 10000
for _ in range(max_iters):
curr_x = x
x = curr_x - gamma * df(curr_x)
if abs(x - curr_x) < eps:
break
return x
df = lambda x: 4 * x**3 - 9 * x**2
res = get_min(6, df, 0.01)
print(f’Minimum at {res:.2f}’)
Out[1]: Minimum at 2.25#NN #gradient
2 456
Что нужно знать программисту для того, чтобы писать хороший код?
Изучить популярный язык или даже несколько недостаточно, чтобы стать программистом. Чтобы писать отличный код, необходимо разбираться в науках и языках. Хотя их не так уж и много, погружение занимает порядочно времени. Но оно того стоит. Так что приступим.
Английский язык
➖Лучше понимать код.
➖Читать мануалы.
➖Взаимодействовать с иностранными заказчиками.
Полезная литература:
English for Information Technology.
Career path Software Engineering.
Oxford English for Information Technology.
Professional English in Use ICT.
Check Your English Vocabulary for Computers and IT.
Математика
➖Большинству программистов хватит умения выполнять простые операции и знания нескольких формул.
➖Продвинутый же уровень математики позволяет программисту писать сложные алгоритмы, которые применяются в графике, аналитике, сортировке, построении маршрутов и машинном обучении.
Полезная литература:
Томас Кормен. «Алгоритмы: построение и анализ».
Дональд Кнут. «Искусство программирования».
Логика
➖Все программы построены на логике. Они получают какие-то данные, проводят вычисления и, в зависимости от результата, делают что-то еще.
➖В реальных программах логики очень много, поэтому в ней нужно разбираться хотя бы на базовом уровне.
Полезная литература:
Непейвода Н.Н. «Прикладная логика».
Владимиров Д.А. «Булевы алгебры».
Статистика
➖Если вы собираетесь заниматься аналитикой, то без статистики никуда. С ее помощью выявляются закономерности, которые помогают в исследованиях.
➖Также с помощью статистики и алгоритмов можно создать искусственный интеллект с машинным обучением — тогда программисту останется лишь подождать, когда ИИ сам найдет закономерности.
Полезная литература:
Чарльз Уилан. «Голая статистика».
Савельев В. «Статистика и котики».
#info
2 456
На гитхабе разместили документ, детально сравнивающий 3 самых популярных мессенджера: Telegram, Viber, Whatsapp.
По ссылке вы найдете огромную таблицу, в которой собрано более 400 параметров для подробного сравнения.
Что в целом приятно, телеграм выигрывает по ряду параметров.
P.S. Постараюсь на днях выложить статью по api QIWI, поскольку некоторым подписчикам тема создания ботов показалась интересной.
2 456
Else в циклах for
# Циклы for и while в Python
# поддерживают кляузу else
# только если цикл завершается
# без вызова break
def contains(haystack, needle):
"""
Бросаем ValueError если needle не
находится в haystack.
"""
for item in haystack:
if item == needle:
break
else:
# else здесь выполнится только
# если цикл не будет прерван break
raise ValueError('Needle not found')
Вывод:
>>> contains([23, 'needle', 0xbadc0ffee], 'needle') None
>>> contains([23, 42, 0xbadc0ffee], 'needle') ValueError: "Needle not found"# Хотя использование else в циклах # не запрещается, можно написать так
def better_contains(haystack, needle):
for item in haystack:
if item == needle:
return
raise ValueError('Needle not found')
# Но если вы хотите писать более
# ‘Pythonic’, лучше всего будет сделать так
if needle not in haystack:
raise ValueError('Needle not found’)2 456
Давно не было новостей.
Во-первых, мы создали бота @ninebetbot. Да, это ставки. Нет, это не реклама. Это полностью созданный нами продукт и я ни копейки не получу за такую “рекламу”, увы. Это был очень интересный опыт работы с различными платежными системами, парсерами, веб-хуками и базами данных. В своей разработке мы использовали апи QIWI как наиболее простую платежную систему. Плюс базы данных mongodb и sqlite3. Можете потыкаться, буду вам очень признателен, если вы все перейдете в бота, а мы в свою очередь проверим его стрессоустойчивость.
Во-вторых, я помню многие из вас жаловались на отсутствие денег. Python разработка открывает перед вами целое многообразие возможностей, одной из которых является разработка ботов в телеграме, а другой — заработок на трейдинге криптовалют. Для последней нужны хорошие знания data science, умение анализировать, а также некоторые знания из математики и статистики. Да и в принципе это довольно таки интересно. В телеграме полно каналов по крипте и “заработку” на ней, и я не собираюсь превращать свой канал в подобие этого. Однако, я могу разбирать некоторые алгоритмы, относящиеся к торговле, на языке Python. Если вам это интересно, прожмите огонек под постом.
В-третьих, для людей, которым торговля не интересна от слова совсем, мы собираемся создать специального бота для обучения написанию собственных ботов и для их монетизации. В планах это давно есть, но пока нет времени. Если вам это интересно, поставьте огонек под постом.
2 456
# Ты можешь проверить наследование
# в классах с помощью встроенной
# функции issubclass()
>>> class BaseClass: pass >>> class SubClass(BaseClass): pass
>>> issubclass(SubClass, BaseClass) True >>> issubclass(SubClass, object) True >>> issubclass(BaseClass, SubClass) False#tips
2 456
Ответ на вопрос “почему именно так?” ниже в статье. На картинку не обращайте внимания, это просто ссылка на книгу в конце статьи.
https://telegra.ph/Tonkosti-Python-06-09
2 456
Luhn algorithm
Алгоритм Луна — алгоритм вычисления контрольной цифры номера пластиковой карты. Не является криптографическим средством, а предназначен в первую очередь для выявления ошибок, вызванных непреднамеренным искажением данных (например, при ручном вводе номера карты).
📎 Алгоритм разработан сотрудником фирмы IBM Гансом Питером Луном.
Наиболее распространённые применения для подсчёта контрольной цифры:
• Номера всех банковских карт
• Номера некоторых дисконтных карт
• Коды социального страхования
• IMEI-коды.
• Расчёт контрольного знака единого 8-значного номера железнодорожного вагона на РЖД.
• Расчёт ICCID — уникальный серийный номер SIM-карты.
Оригинальный алгоритм, описанный разработчиком:
📌Шаг 1.
Цифры проверяемой последовательности нумеруются справа налево.
📌Шаг 2.
Цифры, оказавшиеся на нечётных местах, остаются без изменений.
📌Шаг 3.
Цифры, стоящие на чётных местах, умножаются на 2.
📌Шаг 4.
Если в результате такого умножения возникает число больше 9, оно заменяется суммой цифр получившегося произведения — однозначным числом, то есть цифрой.
📌Шаг 5.
Все полученные в результате преобразования цифры складываются. Если сумма кратна 10, то исходные данные верны.
Попробуем реализовать его на Python.
for i in range(len(digits) - 1, -1, -1):
for c in str((double + 1) * int(digits[i])):
total += int(c)
double = (double + 1) % 2
Основных циклов два. Первый пробегает по всем цифрам в номере (справа налево), второй отвечает за умножение на 2 цифр, стоящих на четных позициях. Переменная total отвечает за сумму цифр — контрольное число.
Вся функция целиком.
def validate_card(card_num):
"""
Input: Card number, integer or string
Output: Valid?, boolean
"""
double = 0
total = 0
digits = str(card_num)
for i in range(len(digits) - 1, -1, -1):
for c in str((double + 1) * int(digits[i])):
total += int(c)
double = (double + 1) % 2
return (total % 10) == 0
#algorithms #python2 456
# Python 3 имеет модуль
# для работы с ip адресами:
>>> import ipaddress
>>> ipaddress.ip_address('192.168.1.2')
IPv4Address('192.168.1.2')
>>> ipaddress.ip_address('2001:af3::')
IPv6Address('2001:af3::’)
# Подробности здесь:
# https://docs.python.org/3/library/ipaddress.html2 456
Целые числа.
Пользователей Python зачастую привлекает его простота, важной частью которой является динамическая типизация. В то время как в языках со статической типизацией, таких как С, необъодимо явным образом объявлять все переменные, языки с динамической типизацией этого не требуют.
Например, в языке С можно описать операцию так:
int result = 0;
for(int i=0; i<100; ++i){
result += i;
}
На языке Python это запишется так:
result = 0
for i in range(100):
result += i
Главное отличие: в языке С типы данных каждой переменной объявлены явным образом.
В Python мы можем сделать так:
x = 4 x = “four”В С это могло бы привести к ошибке компиляции или же неопределенному поведению:
int x = 4; x = “four” // сбойПодобная гибкость делает Python таким удобным и простым в использовании. Однако такая гибкость при работе с типами указывает на то, что переменные Python представляют собой нечто большее, чем просто значение, они содержат также информацию о типе значения. Стандартная реализация языка Python написана на С. Это значит, что каждый объект Python — замаскированная структура С. Посмотрев на исходный код Python 3.4, можно узнать что описание целого типа (long), фактически выглядит так:
struct _longobject {
long ob_refcnt;
PyTypeObject *ob_type;
size_t ob_size;
long ob_digit[1];
Отдельное целое число в языке Python 3.4 состоит из 4 частей:
📌 ob_refcnt - счетчик ссылок, с помощью которого происходит выделение и освобождение памяти
📌 ob_type - тип переменной
📌 ob_size - задает размер следующих элементов данных
📌 ob_digit - содержит фактическое целочисленное значение
Это значит, что существует некоторая избыточность при хранении целого числа в языке Python по сравнению с целыми числами в компилируемых языках.
📎 Целое число в Python — указатель на место в памяти, где хранится вся информация об объекте, включая байты, содержащие само целочисленное значение.
📎 Это влечет за собой последствия в виде дополнительных расходов памяти и/или вычислительного времени, что становится заметно в структурах, объединяющих значительное количество таких объектов.2 456
Правильный ответ
Строки — это неизменяемый тип данных, поэтому произойдет ошибка в строке 2 (простите за тавтологию). Когда вы пытаетесь сделать например вот это:
a = ‘a’ a += ‘b’переменная a на второй строчке заменяется уже другой переменной. 📎изменять строки нельзя, можно только заменять их новыми #string
