- Сравнение объектов
- Итерация и генерация
- Добавление и извелечение
- Интерполяция и подстановка
- Коллекции
- Параметры функций
- Lambda функции
- Импорт модулей
- Классы
- Декораторы
- Функции высшего порядка
- With - менеджер контекста
- Логирование
- Виртуальное окружение
- Популярные библиотеки
Сравнение объектов
== - сравнивает содержимоеis - сравнивает указатель на объект
аналог between в sql:
>>> 0 <= a <= 10
Итерация и генерация
Объект итератор
class Counter:
def __init__(self, low, high):
self.current = low - 1
self.high = high
def __iter__(self):
return self
def __next__(self):
self.current += 1
if self.current < self.high:
return self.current
raise StopIteration
Выражение генератор
def counter(text):
return (n for n in [1,2,3,4,5])
если заменить () на [] то это будет обычный list compreh
Преобразование листа в итератор
iter([1,2,3,4,5])
Генератор
def counter(low, high):
current = low
while current < high:
yield current
current += 1
- при завершении итерации генератора вызывается StopIteration- return в генераторе вызывает StopIteration с переданным значением
- передача сообщения в генератор:
def counter(low, high):
current = low
while current < high:
value = yield current
print(value)
current += 1
gen = counter(1,5)
next(gen) #1
gen.send(55) #55 2
- последовательный вызов 2 генераторов:
def gen_two():
yield from gen
yield from gen2
сначала обойдется gen, потом gen_2- без from сначала будет возвращен итератор 1, потом итератор 2
def gen_two():
yield gen
yield gen2
gt=gen_two()
gt1=next(gt)
gt2=next(gt)
next(gt1) #1
next(gt2) #6
Обход
- foreach
for country in ["Denmark", "Finland", "Norway", "Sweden"]:
print(country)
- обход мапы:
for name, email in emails.items():items() - преобразовывает мапу в список туплов
- обход списка с условием
[expression for item in iterable if condition]
Добавление и извелечение
добавление элемента в список (список мутирует)>>> seeds = ["sesame", "sunflower"] >>> seeds += ["pumpkin"]объединение словарей (3,5+):
zs = {**xs, **ys}
или
zs = xs | yssubstr
seq[start:end:step]reverse str
s[::-1]кроме regex есть встроенные проверки на разные типы у строки:
s.isdigit()
Интерполяция и подстановка
подстановка через f (3.6+)
f'{datetime.now():%Y-%m-%d %H:%M:%S%z}'
подставновка по старому через format
"The novel '{0}' was published in {1}".format("Hard Times", 1854)
"{who} turned {age} this year".format(who="She", age=88)
подстановка с обращением к элементу множества:
{0[1]} #так же можно обращаться объектам через точку
подстановка с форматированием
"{0:25}".format(s) # минимальная ширина поля вывода 25
"{:%B %d, %Y}".format(datetime.now()) #форматирование даты
Удобный просмотрт объекта:
json.dumps(mapping, indent=4, sort_keys=True)поддерживает не все типы данных, для всего лучше подходит:
pprint.pprint(mapping)
Коллекции
именнованный tuple (аналог case class scala)
from dataclasses import dataclass
@dataclass
class Book:
title: str
author: str
аналог
class RegularBook:
def __init__(self, title, author):
self.title = title
self.author = author
получаем из коробки доп. методы
__init__, __repr__, __str__ и __eq__
генерация списка
list(range(n))
В set могут попадать только immutable объекты, к которым применим hash (int, float, str, tuple, bool)
почти все коллекции в питоне мутабельные
Хэш массивы по умолчанию сортированы по очередности вставки, т.к. хэш массив состоит из обычного массива с данными и хэш массив, где в значениях индекс этого обычного массива.
Клонирование коллекции
поверхностное копирование - если в списке есть ссылочные объекты, то копируется ссылка
songs[:] #через равно была бы ссылкадля рекурсивного клонирования всего, нужно исопльзовать:
copy.deepcopy(x)
доступ к словарю с значением по умолчанию
userid.get(userid, 'всем') #всем будет, если userid не найдетсячерез мапу с гетом удобно делать ветвление, если в значение положить функцию
Сортировка по элементу объекта
sorted(xs.items(), key=lambda x: x[1]) #пример: по значению мапы
оператор членства
>>> p = (4, "frog", 9, -33, 9, 2) >>> 2 in p #Trueработает со строками как со списком байт:
"v" in "Peace is no longer permitted during Winterval"разыменование массива в переменные функции
def f(a,b): return a + b f(*[1,2]) #3
Параметры функций
неизменяемые типы: int, float, str, tuple, bool - передается по значениюостальное изменяемое: list, dict, set - передается по ссылке
По этому нельзя передавать пустой лист, т.к. его изменение в функции, изменит его везде
def append_if_even(x, lst=[]): # плохо!распаковка параметров функции
def product(*args):
for arg in args:
**kwargs - содержит именнованные параметры в виде мапы ({name: value})
def print_setup(**options):
print(options['a'])
print_setup(a="123")
отключение позиционных параметров:
def heron2(a, b, c, *, units="meters"):к параметру units можно обратиться только по имени
функции можно создавать с аннотациями типов:
def is_unicode_punctuation(s : str) -> bool:vscode в этом случе использует типы для подсветки и подсказок.
Lambda функции
s = lambda x: "" if x == 1 else "s" s(123) #s
Функции фильтрации, обхода и reduce:
list(map(lambda x: x ** 2, [1, 2, 3, 4])) list(filter(lambda x: x > 0, [1, -2, 3, -4])) functools.reduce(lambda x, y: x * y, [1, 2, 3, 4])
Импорт модулей
import os.pathаналог:
from os import pathпакет - каталог и файл __init__.py
в файле можно указывать:
- список модулей для загрузки всего:
__all__ = ["Bmp", "Jpeg", "Png", "Tiff", "Xpm"]
Предопредленные переменные:
__name__ - будет равно имени модуля при импорте, и __main__ - при запуске из консоли
if __name__ == "__main__":
import doctest
doctest.testmod()
__init.py__ - файл выполняется при импорте модуля (может быть создание каких то переменных, конекстов и т.д.)
динамическое программирование
__import__(...) - импорт модуля по имени
compile(source, file, - объект с результатом компиляции объекта
Классы
все классы неявные наследники objectвстроенные методы:
__new__() - заготовка объекта, вызывается до init
__init__() - конструктор
__eq__() - для сравнения
__repr__() - строка, которую с помощью eval можно превратить обратно в объект
__str__() - представление при выводе в консоль
переменная объявленная в классе может модифицироваться из всех объектов
если создать внутри функции как self.var1 , то только из конкретного объекта
нет приватных методов, но их можно эмулировать через __var (префикс __ - дандер)
переменная переименовывается в _класс__переменная
декоратор @property - метод только для чтения
метод класса - удобно использовать для фабрики, когда возращается новый класс
@classmethod
def margherita(cls):
return cls(['моцарелла', 'помидоры'])
есть множественное наследование
class FileStack(Undo, LoadSave):- если есть одинаковые методы, то приоритет будет у самого левого класса.
вместо общих ошибок, с кастомным текстом, лучше делать сразу кастомные exception через наследование
class NameTooShortError(ValueError):
pass
def validate(name):
if len(name) < 10:
raise NameTooShortError(name)
Декораторы
реализация своего декоратора - определяет новую локальную функцию, которая вызывает оригинальную функцию
def positive_result(function):
def wrapper(*args, **kwargs):
result = function(*args, **kwargs)
assert result >= 0, function.__name__ + "() result isn't >= 0"
return result
wrapper.__name__ = function.__name__
wrapper.__doc__ = function.__doc__
return wrapper
более котороткий вариант, включает доку и название
def positive_result(function):
@functools.wraps(function)
def wrapper(*args, **kwargs):
result = function(*args, **kwargs)
assert result >= 0, function.__name__ + "() result isn't >= 0"
return result
return wrapper
декоратор с параметрами: @bounded(0, 100)
def bounded(minimum, maximum):
def decorator(function):
@functools.wraps(function)
def wrapper(*args, **kwargs):
result = function(*args, **kwargs)
if result < minimum:
return minimum
elif result > maximum:
return maximum
return result
return wrapper
return decorator
в декораторе есть название функции и передаваемые параметры, т.е. его удобно использовать для логирования и отладки (__debug__ - признак отладки)
к функции может быть применено несколько декораторов
Функции высшего порядка
Реализация через класс:
class Strip:
def __init__(self, characters):
self.characters = characters
def __call__(self, string):
return string.strip(self.characters)
strip_punctuation = Strip(",;:.!?") #__init__ класса
strip_punctuation("Land ahoy!") # __call__: 'Land ahoy'
Через вложенные функции:
def make_strip_function(characters):
def strip_function(string):
return string.strip(characters)
return strip_function
Частично подготовить функции можно через functools:
reader = functools.partial(open, mode="rt", encoding="utf8")
reader("file.txt")
With - менеджер контекста
замена try + finnaly
with expression as variable:
suite
expression должен реализовывать __init__, __enter__, __exit__(self, exc_type, exc_value, exc_traceback) - т.е. можно поглотить ошибкуcontextlib - однострочный вариант нескольких конекстов:
with contextlib.nested(open(source), open(target, "w")) as (fin, fout):
for line in fin:
Логирование
Пример логирования в базу данных:
class LogDBHandler(logging.Handler):
def __init__(self, sql_conn, sql_cursor, db_tbl_log):
logging.Handler.__init__(self)
self.sql_cursor = sql_cursor
self.sql_conn = sql_conn
def emit(self, record):
sql = 'INSERT INTO ...'
try:
self.sql_cursor.execute(sql)
self.sql_conn.commit()
except pymssql.Error as e:
print sql
# Make the connection to database for the logger
log_conn = pymssql.connect(db_server, db_user, db_password, db_dbname, 30)
log_cursor = log_conn.cursor()
logdb = LogDBHandler(log_conn, log_cursor, db_tbl_log)
logging.handlers.LogDBHandler = LogDBHandler
Виртуальное окружение
создание виртуальной среды питон в папке ./venv:python3 -m venv venv
- активация (переход) в виртуальную среду
source ~/venv/bin/activateПри активации прописываются пути в path:
PATH="$VIRTUAL_ENV/__VENV_BIN_NAME__:$PATH" export PATHв коде дополнительно появляются переменные __VENV*__ с информацией об окружении
- установка пакетов будет идти в виртуальной папке и теперь не нужны права админа:
pip install schedule
- сохранение установленных пакетов в файл
pip freeze > requirements.txtустановка сохраненных зависимостей:
pip install -r requirements.txt
- список виртуальных окружений
sudo find ~ -name "activate" -type f
- выход из виртуальной среды
deactivate
Операторы Airflow, которые используют виртуальное окружение
- Использование существующего окружения:
my_isolated_task = ExternalPythonOperator(
task_id="my_isolated_task",
python_callable=my_isolated_function,
python=os.environ["ASTRO_PYENV_epo_pyenv"]
)
- Создание своего окружения
Должно быть установлен virtualenv в apache-airflow
pip install apache-airflow[virtualenv]версии питона должны быть установлены и доступы аирфлоу заранее
my_isolated_task = PythonVirtualenvOperator(
task_id="my_isolated_task",
python_callable=my_isolated_function,
requirements=["pandas==1.5.1"],
python_version="3.10", # specify the Python version
)
Комментариев нет:
Отправить комментарий