Hello World – Telegram
Hello World
1.68K subscribers
71 photos
6 videos
3 files
161 links
Be so good that you cannot be ignored. And then, go one step beyond.
Download Telegram
reduce

Продолжая тему itertools. Например, нужно написать функцию, которая принимает список чисел и перемножает их. То есть [1,2,3,4,5,6] даст 1*2*3*4*5*6.

📌Способ 1.

from functools import reduce

In : reduce(lambda x, y: x*y, [1, 2, 3, 4, 5, 6])
Out: 720


📌Способ 2.

import operator
import functools

In : functools.reduce(operator.mul, [1, 2, 3, 4, 5, 6], 1)
Out: 720


📌Способ 3.

import numpy as np

In : np.prod(np.array([1, 2, 3, 4, 5, 6]))
Out: 720


#tips #itertools #reduce
Что выведет следующий код?

In[1]: qwe = ‘qwe’
In[2]: qwe[0] = ‘a’
In[3]: print(qwe)
Правильный ответ

Строки — это неизменяемый тип данных, поэтому произойдет ошибка в строке 2 (простите за тавтологию). Когда вы пытаетесь сделать например вот это:
a = ‘a’
a += ‘b’


переменная a на второй строчке заменяется уже другой переменной.

📎изменять строки нельзя, можно только заменять их новыми

#string
Целые числа.

Пользователей 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 — указатель на место в памяти, где хранится вся информация об объекте, включая байты, содержащие само целочисленное значение.
📎 Это влечет за собой последствия в виде дополнительных расходов памяти и/или вычислительного времени, что становится заметно в структурах, объединяющих значительное количество таких объектов.
# 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.html
Теоретический_миниму.pdf
10.3 MB
Отличная книга по CS, рекомендую к прочтению.
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 #python
# Ты можешь проверить наследование
# в классах с помощью встроенной
# функции issubclass()

>>> class BaseClass: pass
>>> class SubClass(BaseClass): pass


>>> issubclass(SubClass, BaseClass)
True
>>> issubclass(SubClass, object)
True
>>> issubclass(BaseClass, SubClass)
False


#tips
Давно не было новостей.

Во-первых, мы создали бота @ninebetbot. Да, это ставки. Нет, это не реклама. Это полностью созданный нами продукт и я ни копейки не получу за такую “рекламу”, увы. Это был очень интересный опыт работы с различными платежными системами, парсерами, веб-хуками и базами данных. В своей разработке мы использовали апи QIWI как наиболее простую платежную систему. Плюс базы данных mongodb и sqlite3. Можете потыкаться, буду вам очень признателен, если вы все перейдете в бота, а мы в свою очередь проверим его стрессоустойчивость.

Во-вторых, я помню многие из вас жаловались на отсутствие денег. Python разработка открывает перед вами целое многообразие возможностей, одной из которых является разработка ботов в телеграме, а другой — заработок на трейдинге криптовалют. Для последней нужны хорошие знания data science, умение анализировать, а также некоторые знания из математики и статистики. Да и в принципе это довольно таки интересно. В телеграме полно каналов по крипте и “заработку” на ней, и я не собираюсь превращать свой канал в подобие этого. Однако, я могу разбирать некоторые алгоритмы, относящиеся к торговле, на языке Python. Если вам это интересно, прожмите огонек под постом.

В-третьих, для людей, которым торговля не интересна от слова совсем, мы собираемся создать специального бота для обучения написанию собственных ботов и для их монетизации. В планах это давно есть, но пока нет времени. Если вам это интересно, поставьте огонек под постом.
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’)
На гитхабе разместили документ, детально сравнивающий 3 самых популярных мессенджера: Telegram, Viber, Whatsapp.

По ссылке вы найдете огромную таблицу, в которой собрано более 400 параметров для подробного сравнения.

Что в целом приятно, телеграм выигрывает по ряду параметров.

P.S. Постараюсь на днях выложить статью по api QIWI, поскольку некоторым подписчикам тема создания ботов показалась интересной.
Что нужно знать программисту для того, чтобы писать хороший код?

Изучить популярный язык или даже несколько недостаточно, чтобы стать программистом. Чтобы писать отличный код, необходимо разбираться в науках и языках. Хотя их не так уж и много, погружение занимает порядочно времени. Но оно того стоит. Так что приступим.

Английский язык
Лучше понимать код.
Читать мануалы.
Взаимодействовать с иностранными заказчиками.

Полезная литература:
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
Градиентный спуск.

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

Что такое градиентный спуск.

Градиентный спуск — метод нахождения минимального значения функции многих переменных. Минимизация любой такой функции означает поиск самой глубокой впадины в этой функции. Поиск минимума в машинном обучении означает получение наименьшей возможной ошибки или повышение точности модели. Мы увеличиваем точность, перебирая набор учебных данных при настройке параметров нашей модели (весов и смещений).

Суть алгоритма – процесс получения наименьшего значения ошибки. Аналогично это можно рассматривать как спуск во впадину в попытке найти золото на дне ущелья (самое низкое значение ошибки).

Перейдем к практике.

Рассмотрим самый простейший случай применения градиентного спуска, а именно, поиск минимума заданной функции.
В одномерном случае, градиент функции (в проекции на выбранную ось) представяет собой обычную одномерную производную.

Возьмем функцию 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
# Способы проверки того, что
# все элементы списка одинаковы:

>>> 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 аргументы.

>>> 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.

Пара коротких заметок по поводу словарей.

📌 Для того, чтобы взять “срез” словаря, можно поступить так:
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