Function argument unpacking
Создадим простую функцию.
Создадим к ней дополнительно кортеж и словарь.
Теперь мы можем передавать их в нашу функцию вот так просто, это удобно:
#tips
Создадим простую функцию.
def myfunc(x, y, z):
print(x, y, z)
Создадим к ней дополнительно кортеж и словарь.
tuple_vec = (1, 0, 1)
dict_vec = {'x': 1, 'y': 0, 'z': 1}
Теперь мы можем передавать их в нашу функцию вот так просто, это удобно:
>>> myfunc(*tuple_vec)
1, 0, 1
>>> myfunc(**dict_vec)
1, 0, 1
#tips
Есть ли разница между [] и list()?
В принципе результат будет одним и тем же, но давайте заглянем глубже:
Инициализация листа с помощью конструктора list() выглядит как минимум в 4-5 раз медленнее. Попробуем заглянуть внутрь с помощью модуля dis, который служит для изучения байткода Python’a.
Ответ заключается в том, что в то случае когда мы выбираем list() вместо [] мы теряем вычислительное время на “избыточный” вызов самой функции list().
📎 Во многих случаях это не настолько важно, поскольку мы имеем дело с микросекундами. Однако стоит об этом помнить, если ты имеешь дело с big data.
#list
>>> f = []
>>> f = list()
В принципе результат будет одним и тем же, но давайте заглянем глубже:
>>> timeit.timeit(‘[]’, number=10**8)
2.25569809000001
>>> timeit.timeit(‘list()’, number=10**8)
10.330681907999995
Инициализация листа с помощью конструктора list() выглядит как минимум в 4-5 раз медленнее. Попробуем заглянуть внутрь с помощью модуля dis, который служит для изучения байткода Python’a.
>>> dis.dis('f=[]')
1 0 BUILD_LIST 0
2 STORE_NAME 0 (f)
4 LOAD_CONST 0 (None)
6 RETURN_VALUE
>>> dis.dis('f=list()')
1 0 LOAD_NAME 0 (list)
2 CALL_FUNCTION 0
4 STORE_NAME 1 (f)
6 LOAD_CONST 0 (None)
8 RETURN_VALUEОтвет заключается в том, что в то случае когда мы выбираем list() вместо [] мы теряем вычислительное время на “избыточный” вызов самой функции list().
📎 Во многих случаях это не настолько важно, поскольку мы имеем дело с микросекундами. Однако стоит об этом помнить, если ты имеешь дело с big data.
#list
Какими модулями чаще пользуешься?
Anonymous Poll
25%
numpy/scipy
5%
matplotlib/seaborn
38%
requests/urllib2
9%
PIL/pillow
9%
threading/multiprocessing
14%
pandas/scikit-learn
Что выведет следующий код?
def check_size(val):
if val > 0x18:
val >>= 1
return val
def dga(seed):
out = ""
for k, n in enumerate([1, 3, 5, 7, 0xb, 0xd]):
i = check_size(k * seed)
out += chr(i + 0x61)
return out
if __name__ == '__main__':
print('al' + dga(1))
Python's null Equivalent: None
Эквивалент ключевого слова null в Python это None.
Многие утверждают, что слово null несколько эзотерично. Это не самое дружелюбное слово для начинающих программистов. Кроме того, None относится именно к намеченной функциональности — это ничто и не имеет никакого поведения.
Стоит отметить пару особенностей работы с None:
📎 Python является объектно ориентированным языком, поэтому None — это тоже объект:
📎 Самый лучший вариант проверки на None — с помощью оператора is:
Почему так? Если переопределить оператор сравнения в пользовательском классе, это может привести к неожиданному результату:
Вывод:
#tips #None
Эквивалент ключевого слова null в Python это None.
Многие утверждают, что слово null несколько эзотерично. Это не самое дружелюбное слово для начинающих программистов. Кроме того, None относится именно к намеченной функциональности — это ничто и не имеет никакого поведения.
Стоит отметить пару особенностей работы с None:
📎 Python является объектно ориентированным языком, поэтому None — это тоже объект:
>>> type(None)
< class 'NoneType’>
📎 Самый лучший вариант проверки на None — с помощью оператора is:
number = None
if number is None:
print(‘None’)
Почему так? Если переопределить оператор сравнения в пользовательском классе, это может привести к неожиданному результату:
class MyClass:
def __eq__(self, my_object):
return True
my_class = MyClass()
if my_class is None:
print('my_class is None, using the is keyword')
else:
print('my_class is not None, using the is keyword')
if my_class == None:
print('my_class is None, using the == syntax')
else:
print('my_class is not None, using the == syntax’)
Вывод:
my_class is not None, using the is keyword
my_class is None, using the == syntax
#tips #None
Итераторы
Итератор – это интерфейс, который позволяет перебирать элементы последовательности. Он используется, например, в цикле for ... in ..., но этот механизм скрыт от глаз разработчика. При желании итератор можно получить воспользовавшись функцией iter().
Чтобы получить следующий элемент коллекции или строки, нужно передать итератор функции next().
Пример простого итератора:
Вывод:
Итератор – это интерфейс, который позволяет перебирать элементы последовательности. Он используется, например, в цикле for ... in ..., но этот механизм скрыт от глаз разработчика. При желании итератор можно получить воспользовавшись функцией iter().
Чтобы получить следующий элемент коллекции или строки, нужно передать итератор функции next().
Пример простого итератора:
class SimpleIterator:
def __iter__(self):
return self
def __init__(self, limit):
self.limit = limit
self.counter = 0
def __next__(self):
if self.counter < self.limit:
self.counter += 1
return 1
else:
raise StopIteration
Вывод:
simple_iter = SimpleIterator(5)
for i in simple_iter:
print(i)
1
1
1
1
1
“is” vs “==“
Два списка указывают на один и тот же объект:
Результат:
Пробуем создать абсолютно новый объект:
Результат:
📎 is возвратит True, если обе переменные ссылаются на один объект
📎 == возвратит True, если сравниваемые объекты идентичны
#tips
Два списка указывают на один и тот же объект:
>>> a = [1, 2, 3]
>>> b = a
Результат:
>>> a is b
True
>>> a == b
True
Пробуем создать абсолютно новый объект:
>>> c = a[:]
Результат:
>>> a == c
True
>>> a is c
False
📎 is возвратит True, если обе переменные ссылаются на один объект
📎 == возвратит True, если сравниваемые объекты идентичны
#tips
PEP8
PEP 8 де-факто представляет собой руководство по стилю написания кода Python. В нем рассматриваются соглашения по именованию, структура кода, пустые области (табуляция против пробелов) и другие аналогичные темы.
Писать код с учетом принципов PEP 8 — хорошая идея (помогает разработчикам создавать более стабильный код). С помощью программы pycodestyle, которая запускается из командной строки, можно проверить код на соответствие принципам PEP 8. Для установки этой программы введите в терминале такую команду:
Пример использования:
#pep8
PEP 8 де-факто представляет собой руководство по стилю написания кода Python. В нем рассматриваются соглашения по именованию, структура кода, пустые области (табуляция против пробелов) и другие аналогичные темы.
Писать код с учетом принципов PEP 8 — хорошая идея (помогает разработчикам создавать более стабильный код). С помощью программы pycodestyle, которая запускается из командной строки, можно проверить код на соответствие принципам PEP 8. Для установки этой программы введите в терминале такую команду:
$ pip3 install pycodestyle
Пример использования:
$ pycodestyle smooth.py
smooth.py:3:1: E265 block comment should start with '# '
smooth.py:4:1: E265 block comment should start with '# '
smooth.py:5:1: E265 block comment should start with '# '
smooth.py:10:51: E251 unexpected spaces around keyword / parameter equals
smooth.py:10:53: E251 unexpected spaces around keyword / parameter equals
smooth.py:14:33: W292 no newline at end of file
#pep8
PyPI
pycodestyle
Python style guide checker
First Class functions
Свойства функций первого класса:
📎 Функция является экземпляром типа object.
📎 Можно сохранить функцию в переменной.
📎 Можно передать функцию в качестве параметра другой функции.
📎 Можно вернуть функцию из функции.
📎 Можно хранить их в структурах данных, таких как хеш-таблицы, списки, словари, etc
Хранение функции в списке:
Вывод:
Возврат функции из другой функции:
Вывод:
#tips #closure #firstclassfunctions
Свойства функций первого класса:
📎 Функция является экземпляром типа object.
📎 Можно сохранить функцию в переменной.
📎 Можно передать функцию в качестве параметра другой функции.
📎 Можно вернуть функцию из функции.
📎 Можно хранить их в структурах данных, таких как хеш-таблицы, списки, словари, etc
Хранение функции в списке:
def myfunc(a, b):
return a + b
Вывод:
>>> funcs = [myfunc]
>>> funcs[0]
<function myfunc at 0x107012230>
>>> funcs[0](2, 3)
5
Возврат функции из другой функции:
def outer(x):
def inner(y):
return x+y
return inner
closure = outer(15)
Вывод:
>>> closure(10)
25
#tips #closure #firstclassfunctions
256 — существующий объект, а 257 — нет
При запуске Python в памяти размещаются числа от -5 до 256. Они используются часто, так что целесообразно держать их наготове.
Интерпретатор оказался не так умён, и во время исполнения y = 257 не понял, что мы уже создали целое число со значением 257, поэтому создаёт в памяти другой объект.
#tips
При запуске Python в памяти размещаются числа от -5 до 256. Они используются часто, так что целесообразно держать их наготове.
>>> a = 256
>>> b = 256
>>> id(a)
4478229648
>>> id(b)
4478229648
Интерпретатор оказался не так умён, и во время исполнения y = 257 не понял, что мы уже создали целое число со значением 257, поэтому создаёт в памяти другой объект.
>>> a = 257
>>> b = 257
>>> id(a)
4481407824
>>> id(b)
4481407600
#tips
timeit
Модуль timeit позволяет измерить время выполнения небольших кусочков кода:
#timeit #tips
Модуль timeit позволяет измерить время выполнения небольших кусочков кода:
>>> import timeit
>>> timeit.timeit('"-".join(str(n) for n in range(100))',
number=10000)
0.3412662749997253
>>> timeit.timeit('"-".join([str(n) for n in range(100)])',
number=10000)
0.2996307989997149>>> timeit.timeit('"-".join(map(str, range(100)))',
number=10000)
0.24581470699922647#timeit #tips
Использование dict() вместо цепочек if-elif-else
В некоторых случаях удобнее и лучше использовать dict() вместо цепочек условных операторов.
Данный код, если можно так выразиться, более “pythonic”:
Вывод:
#tips #dict
В некоторых случаях удобнее и лучше использовать dict() вместо цепочек условных операторов.
def dispatch_if(operator, x, y):
if operator == 'add':
return x + y
elif operator == 'sub':
return x - y
elif operator == 'mul':
return x * y
elif operator == 'div':
return x / y
else:
return None
Данный код, если можно так выразиться, более “pythonic”:
def dispatch_dict(operator, x, y):
return {
'add': lambda: x + y,
'sub': lambda: x - y,
'mul': lambda: x * y,
'div': lambda: x / y,
}.get(operator, lambda: None)()
Вывод:
>>> dispatch_if('mul', 2, 8)
16
>>> dispatch_dict('mul', 2, 8)
16
>>> dispatch_if('unknown', 2, 8)
None
>>> dispatch_dict('unknown', 2, 8)
None#tips #dict
🐍 Немного новостей за прошедшую неделю
🔸Apple опубликовала финальный релиз языка программирования Swift 5 для iOS, macOS, watchOS и tvOS. Главное улучшение — стабильность ABI, что обеспечивает бинарную совместимость приложений и библиотек, скомпилированных разными версиями языка.
🔸TypeScript и Kotlin получили статус самых быстрорастущих языков программирования в рейтинге RedMonk. Учитывались такие параметры, как используемость и интерес со стороны разработчиков.
🔸В MIT создали новый алгоритм, который в 200 раз ускоряет разработку нейросетей.
🔸Microsoft открыла исходный код проекта Pyright, в рамках которого развивается система для применения статической типизации в приложениях на языке Python.
#news
🔸Apple опубликовала финальный релиз языка программирования Swift 5 для iOS, macOS, watchOS и tvOS. Главное улучшение — стабильность ABI, что обеспечивает бинарную совместимость приложений и библиотек, скомпилированных разными версиями языка.
🔸TypeScript и Kotlin получили статус самых быстрорастущих языков программирования в рейтинге RedMonk. Учитывались такие параметры, как используемость и интерес со стороны разработчиков.
🔸В MIT создали новый алгоритм, который в 200 раз ускоряет разработку нейросетей.
🔸Microsoft открыла исходный код проекта Pyright, в рамках которого развивается система для применения статической типизации в приложениях на языке Python.
#news
Какой самый лучший способ понять как работает git?
Правильно, написать его. А писать его на Python вдвойне приятнее!
Автор статьи по пунктам разбирает написание собственной системы контроля версий.
Как по мне, это отличный способ изучить git и к тому же потренировать свои навыки программирования на Python.
#git
Правильно, написать его. А писать его на Python вдвойне приятнее!
Автор статьи по пунктам разбирает написание собственной системы контроля версий.
Как по мне, это отличный способ изучить git и к тому же потренировать свои навыки программирования на Python.
#git
geopy
Программистам может быть сложно ориентироваться в географии. Однако, модуль geopy всё упрощает:
Он работает путём абстрагирования API разных сервисов геокодирования. Этот модуль даёт возможность узнать полный адрес места, его долготу и широту и даже высоту.
Также в нём есть полезный класс Distance. Он высчитывает расстояние между двумя местами в удобной единице измерения.
#tips #geopy
Программистам может быть сложно ориентироваться в географии. Однако, модуль geopy всё упрощает:
$ pip install geopy
Он работает путём абстрагирования API разных сервисов геокодирования. Этот модуль даёт возможность узнать полный адрес места, его долготу и широту и даже высоту.
Также в нём есть полезный класс Distance. Он высчитывает расстояние между двумя местами в удобной единице измерения.
from geopy import GoogleV3
place = "221b Baker Street, London"
location = GoogleV3().geocode(place)
print(location.address)
print(location.location)
#tips #geopy
Python HTTP server
Python позволяет поднять простой http сервер с помощью одной строчки в терминале:
По умолчанию он использует 8000й порт и предоставляет доступ к текущей директории терминала.
#tips #http
Python позволяет поднять простой http сервер с помощью одной строчки в терминале:
# Python 3.x
$ python3 -m http.server
# Python 2.x
$ python -m SimpleHTTPServer 8000
По умолчанию он использует 8000й порт и предоставляет доступ к текущей директории терминала.
http://localhost:8000#tips #http
Поиск палиндромов в слове
Небольшой, но действенный код для поиска всех палиндромов в слове:
И на закуску несколько способов проверки на палиндром.
📎 Так как любое слово это итерируемый объект, можно просто проверить его циклом:
📎 Перейти к списку, и воспользоваться функцией reversed:
📎 И самый удобный способ, со срезом списка:
#tips #palindrome
Небольшой, но действенный код для поиска всех палиндромов в слове:
def get_palindrom(text):
text = text.lower()
results = []
for i in range(len(text)):
for j in range(0, i):
chunk = text[j:i + 1]
if chunk == chunk[::-1]:
results.append(chunk)
return results
И на закуску несколько способов проверки на палиндром.
📎 Так как любое слово это итерируемый объект, можно просто проверить его циклом:
for index in range(len(word)):
if word[index] == word[-(index + 1)]:
results.append(word)
📎 Перейти к списку, и воспользоваться функцией reversed:
if list(word) == list(reversed(word)):
results.append(word)
📎 И самый удобный способ, со срезом списка:
if word == word[::-1]:
results.append(word)
#tips #palindrome
Generators & iterators (1/3)
Рано или поздно всякий Python-разработчик сталкивается с осознанием того, что он не до конца понимает смысл и различия следующих понятий:
🔸контейнер (container)
🔸итерируемый объект (iterable)
🔸итератор (iterator)
🔸генератор (generator)
🔸генераторное выражение (generator expression)
🔸списковое включение (list comprehension)
Контейнеры
Контейнер — это тип данных, предназначенный для хранения элементов и предоставляющий набор операций для работы с ними. Сами контейнеры и, как правило, их элементы хранятся в памяти. В Python существует масса разнообразных контейнеров, среди которых всем хорошо знакомые:
🔸list, deque, …
🔸set, frozensets, …
🔸dict, defaultdict, OrderedDict, Counter, …
🔸tuple, namedtuple, …
🔸str
📎Технически, объект является контейнером тогда, когда он предоставляет возможность определить наличие или отсутствие в нём конкретного элемента.
📎Обратите внимание, что несмотря на то, что большинство контейнеров предоставляют возможность извлекать из них любой элемент, само по себе наличие этой возможности не делает объект контейнером, а лишь итерируемым объектом.
Итерируемые объекты
Как было уже сказано, большинство контейнеров являются итерируемыми. Но в то же время множество других типов данных являются итерируемыми, например, файлы, сокеты и тому подобные. В то время как контейнеры обычно содержат конечное количество элементов, просто итерируемый объект может представлять собой источник бесконечных данных.
Итерируемым объектом является любой объект, который может предоставить итератор, который, в свою очередь, и возвращает отдельные элементы. На первый взгляд это звучит немного странновато, но тем не менее очень важно понимать разницу между интерируемым объектом и итератором. Рассмотрим пример:
Здесь х — это итерируемый объект, в то время как y и z два отдельных экземпляра итератора, производящего значения из итерируемого объекта x. Как мы видим, y и z сохраняют состояние между вызовами next(). В данном примере в качестве источника данных для итератора используется список, но это не является обязательным условием.
📎Часто, чтобы сократить объем кода, классы итерируемых объектов имплементируют сразу оба метода:
#tips #generators
Рано или поздно всякий Python-разработчик сталкивается с осознанием того, что он не до конца понимает смысл и различия следующих понятий:
🔸контейнер (container)
🔸итерируемый объект (iterable)
🔸итератор (iterator)
🔸генератор (generator)
🔸генераторное выражение (generator expression)
🔸списковое включение (list comprehension)
Контейнеры
Контейнер — это тип данных, предназначенный для хранения элементов и предоставляющий набор операций для работы с ними. Сами контейнеры и, как правило, их элементы хранятся в памяти. В Python существует масса разнообразных контейнеров, среди которых всем хорошо знакомые:
🔸list, deque, …
🔸set, frozensets, …
🔸dict, defaultdict, OrderedDict, Counter, …
🔸tuple, namedtuple, …
🔸str
📎Технически, объект является контейнером тогда, когда он предоставляет возможность определить наличие или отсутствие в нём конкретного элемента.
📎Обратите внимание, что несмотря на то, что большинство контейнеров предоставляют возможность извлекать из них любой элемент, само по себе наличие этой возможности не делает объект контейнером, а лишь итерируемым объектом.
Итерируемые объекты
Как было уже сказано, большинство контейнеров являются итерируемыми. Но в то же время множество других типов данных являются итерируемыми, например, файлы, сокеты и тому подобные. В то время как контейнеры обычно содержат конечное количество элементов, просто итерируемый объект может представлять собой источник бесконечных данных.
Итерируемым объектом является любой объект, который может предоставить итератор, который, в свою очередь, и возвращает отдельные элементы. На первый взгляд это звучит немного странновато, но тем не менее очень важно понимать разницу между интерируемым объектом и итератором. Рассмотрим пример:
>>> x = [1, 2, 3]
>>> y = iter(x)
>>> z = iter(x)
>>> next(y)
1
>>> next(y)
2
>>> next(z)
1
Здесь х — это итерируемый объект, в то время как y и z два отдельных экземпляра итератора, производящего значения из итерируемого объекта x. Как мы видим, y и z сохраняют состояние между вызовами next(). В данном примере в качестве источника данных для итератора используется список, но это не является обязательным условием.
📎Часто, чтобы сократить объем кода, классы итерируемых объектов имплементируют сразу оба метода:
__iter()__ и __next()__, при этом __iter()__ возвращает self. Таким образом класс одновременно является и итерируемым и итератором самого себя. Однако, лучшей практикой всё же считается в качестве итератора возвращать отдельный объект.#tips #generators
Итерируемые объекты
Итак, когда выполняется следующий код:
Вот что происходит на самом деле:
📌Если диассемблировать код, представленный выше, мы обнаружим вызов GET_ITER, который по сути является следствием вызова iter(x). Инструкция FOR_ITER является эквивалентом многократного вызова next() до тех пор, пока не будет возвращён последний элемент. Этого, правда, не видно в байт-коде из-за оптимизаций, вносимых интерпретатором.
#tips #cycles
Итак, когда выполняется следующий код:
x = [1, 2, 3]
for item in x:
pass
Вот что происходит на самом деле:
>>> import dis
>>> x = [1, 2, 3]
>>> dis.dis('for _ in x: pass')
1 0 SETUP_LOOP 14 (to 17)
3 LOAD_NAME 0 (x)
6 GET_ITER
>> 7 FOR_ITER 6 (to 16)
10 STORE_NAME 1 (_)
13 JUMP_ABSOLUTE 7
>> 16 POP_BLOCK
>> 17 LOAD_CONST 0 (None)
20 RETURN_VALUE
📌Если диассемблировать код, представленный выше, мы обнаружим вызов GET_ITER, который по сути является следствием вызова iter(x). Инструкция FOR_ITER является эквивалентом многократного вызова next() до тех пор, пока не будет возвращён последний элемент. Этого, правда, не видно в байт-коде из-за оптимизаций, вносимых интерпретатором.
#tips #cycles