- Сравнение объектов
- Итерация и генерация
- Добавление и извелечение
- Интерполяция и подстановка
- Коллекции
- Параметры функций
- 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
Обход
- foreachfor 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 + finnalywith expression as variable: suiteexpression должен реализовывать __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 )
Комментариев нет:
Отправить комментарий