Когда вы создаете кастомный метод
Пример простого кода:
Проблема возникает, если вы вызываете
Для решения этой проблемы можно использовать декоратор
Теперь код работает корректно:
📲 Мы в MAX
👉@BookPython
__repr__ для объекта, обычно нужно включить представление его атрибутов. Однако важно помнить, что нужно явно вызывать repr(), так как форматирование вызывает str() вместо repr().Пример простого кода:
class Pair:
def __init__(self, left, right):
self.left = left
self.right = right
def __repr__(self):
class_name = type(self).__name__
repr_left = repr(self.left)
repr_right = repr(self.right)
return f'{class_name}({repr_left}, {repr_right})'
Проблема возникает, если вы вызываете
repr для объекта, который содержит ссылку на самого себя. Это может привести к рекурсии:
In : p = Pair(1, 2)
In : p
Out: Pair(1, 2)
In : p.right = p
In : p
Out: [...]
RecursionError: maximum recursion depth exceeded while calling a Python object
Для решения этой проблемы можно использовать декоратор
reprlib.recursive_repr, который обрабатывает рекурсивные вызовы:
@reprlib.recursive_repr()
def __repr__(self):
class_name = type(self).__name__
repr_left = repr(self.left)
repr_right = repr(self.right)
return f'{class_name}({repr_left}, {repr_right})'
Теперь код работает корректно:
In : p = Pair(1, 2)
In : p.right = p
In : p
Out: Pair(1, ...)
👉@BookPython
Please open Telegram to view this post
VIEW IN TELEGRAM
❤2👍1
Тесты могут требовать временные файлы или директории. Для этого отлично подойдет модуль
Так как временные файлы обычно нужно удалять после использования,
📲 Мы в MAX
👉@BookPython
tempfile.Так как временные файлы обычно нужно удалять после использования,
tempfile предоставляет как контекстный менеджер, так и простые функции:
import os
import tempfile
with tempfile.TemporaryDirectory() as dir_path:
open(os.path.join(dir_path, 'a'), 'w').close()
open(os.path.join(dir_path, 'b'), 'w').close()
open(os.path.join(dir_path, 'c'), 'w').close()
assert files_of(dir_path) == ['a', 'b', 'c']
👉@BookPython
Please open Telegram to view this post
VIEW IN TELEGRAM
👍3
Нативные значения
Это означает, что в большинстве случаев вы работаете с приближениями, а не с точными значениями:
Модуль
Однако и этого может быть недостаточно:
Для точных вычислений можно использовать
Очевидным ограничением остается то, что иррациональные числа (например, π) все равно будут представлены только в приближенной форме.
📲 Мы в MAX
👉@BookPython
float в Python используют аппаратные возможности вашего компьютера, поэтому любое значение внутренне представлено в виде двоичной дроби.Это означает, что в большинстве случаев вы работаете с приближениями, а не с точными значениями:
In : format(0.1, '.17f')
Out: '0.10000000000000001'
Модуль
decimal позволяет использовать десятичную арифметику с произвольной точностью:
In : Decimal(1) / Decimal(3)
Out: Decimal('0.3333333333333333333333333333')
Однако и этого может быть недостаточно:
In [61]: Decimal(1) / Decimal(3) * Decimal(3) == Decimal(1)
Out[61]: False
Для точных вычислений можно использовать
fractions, где любое число хранится в виде рационального:
In : Fraction(1) / Fraction(3) * Fraction(3) == Fraction(1)
Out: True
Очевидным ограничением остается то, что иррациональные числа (например, π) все равно будут представлены только в приближенной форме.
👉@BookPython
Please open Telegram to view this post
VIEW IN TELEGRAM
👍2💩2
UTF-8 - это кодировка с переменной длиной. Один символ может быть закодирован с использованием одного, двух, трёх или четырёх байтов. Это означает, что нельзя начать чтение строки в кодировке UTF-8 с произвольного байта, так как это может случайно разрушить символ:
Также это означает, что для пропуска первых
Однако можно пропустить фиксированное количество байтов, принимая во внимание некоторые особенности. Вот как может быть закодирован символ в UTF-8:
Как видно, байт является начальным байтом символа, если его вид не совпадает с
Пример использования:
📲 Мы в MAX
👉@BookPython
In : lion = 'Löwe'
In : lion.encode('utf-8')[2:]
Out: b'\xb6we'
In : lion.encode('utf-8')[2:].decode('utf-8')
...
UnicodeDecodeError: 'utf-8' codec can't decode byte 0xb6 in position 0: invalid start byte
Также это означает, что для пропуска первых
N символов строки их необходимо прочитать и декодировать. Рассчитать смещение заранее невозможно.Однако можно пропустить фиксированное количество байтов, принимая во внимание некоторые особенности. Вот как может быть закодирован символ в UTF-8:
0xxxxxxx
110xxxxx 10xxxxxx
1110xxxx 10xxxxxx 10xxxxxx
11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
Как видно, байт является начальным байтом символа, если его вид не совпадает с
10xxxxxx. Такие байты называются продолжением символа (continuation bytes). Давайте пропустим их:
def cut_bytes(s, n):
result = s.encode('utf-8')[n:]
mask = int('11000000', 2)
conbyte = int('10000000', 2)
while result[0] and result[0] & mask == conbyte:
result = result[1:]
return result.decode('utf-8')
Пример использования:
In : cut_bytes(lion, 2)
Out: 'we'
In : cut_bytes(lion, 1)
Out: 'öwe'
👉@BookPython
Please open Telegram to view this post
VIEW IN TELEGRAM
👍2❤1
Иногда вам нужно запустить блок кода с несколькими контекстными менеджерами. Например:
Начиная с Python 2.7 и 3.1, это можно сделать с помощью одного выражения
До этого можно было использовать функцию
Однако в современных версиях Python эта функция устарела и вызывает предупреждение. Вместо неё рекомендуется использовать более продвинутый инструмент —
Это особенно полезно, когда количество контекстных менеджеров неизвестно заранее.
📲 Мы в MAX
👉@BookPython
with open('f') as f:
with open('g') as g:
with open('h') as h:
pass
Начиная с Python 2.7 и 3.1, это можно сделать с помощью одного выражения
with:
o = open
with o('f') as f, o('g') as g, o('h') as h:
pass
До этого можно было использовать функцию
contextlib.nested:
with nested(o('f'), o('g'), o('h')) as (f, g, h):
pass
Однако в современных версиях Python эта функция устарела и вызывает предупреждение. Вместо неё рекомендуется использовать более продвинутый инструмент —
contextlib.ExitStack. Он позволяет войти в любое количество контекстов в произвольное время, но гарантирует их корректное завершение:
from contextlib import ExitStack
with ExitStack() as stack:
f = stack.enter_context(o('f'))
g = stack.enter_context(o('g'))
other = [
stack.enter_context(o(filename))
for filename in filenames
]
Это особенно полезно, когда количество контекстных менеджеров неизвестно заранее.
👉@BookPython
Please open Telegram to view this post
VIEW IN TELEGRAM
❤2👍1
Когда корутина asyncio хочет остановиться и взаимодействовать с циклом событий (event loop), она использует
Когда корутина ожидает (
Какое значение возвращает
Почему возникает эта ошибка? Как asyncio понимает, что это вы используете
📲 Мы в MAX
👉@BookPython
await obj (или yield from obj до Python 3.6). Объект obj должен быть другой корутиной, объектом asyncio.Future или любым пользовательским объектом, похожим на Future (любой объект, у которого определен метод __await__).
async def coroutine():
await another_coroutine()
async def another_coroutine():
future = asyncio.Future()
await future
loop = asyncio.get_event_loop()
loop.run_until_complete(coroutine())
Когда корутина ожидает (
await) другую корутину, вторая начинает выполняться вместо первой. Если она ожидает третью, то выполняется третья. Это продолжается до тех пор, пока какая-нибудь корутина не ожидает объект Future. Объект Future фактически возвращает значение, и тогда цикл событий (event loop) получает управление.Какое значение возвращает
Future? Оно возвращает сам себя. Можете ли вы напрямую использовать yield для Future? Нет, это внутренняя деталь, о которой вам обычно не нужно беспокоиться.
class Awaitable:
def __await__(self):
future = asyncio.Future()
yield future
# RuntimeError: yield was used
# instead of yield from in task
async def coroutine():
await Awaitable()
loop = asyncio.get_event_loop()
loop.run_until_complete(coroutine())
Почему возникает эта ошибка? Как asyncio понимает, что это вы используете
yield для Future, а не сам Future? Есть простая защита: Future устанавливает внутренний флаг перед тем, как вернуть управление.👉@BookPython
Please open Telegram to view this post
VIEW IN TELEGRAM
👍2
Рассмотрим следующую иерархию классов:
В каком порядке будет производиться поиск метода
Чтобы исправить эту проблему, Python использует линеаризацию C3 (C3 superclass linearization), алгоритм, который всегда ищет метод сначала во всех дочерних классах, а затем уже в родительских.
Пример вывода MRO (Method Resolution Order):
📲 Мы в MAX
👉@BookPython
class GrandParent:
pass
class Parent1(GrandParent):
pass
class Parent2(GrandParent):
pass
class Child(Parent1, Parent2):
pass
В каком порядке будет производиться поиск метода
Child.x()? Наивный подход заключается в рекурсивном поиске через все родительские классы, что даст порядок: Child, Parent1, GrandParent, Parent2. Такой метод используется во многих языках программирования, однако он не совсем логичен, так как Parent2 более специфичен, чем GrandParent, и его нужно проверять раньше.Чтобы исправить эту проблему, Python использует линеаризацию C3 (C3 superclass linearization), алгоритм, который всегда ищет метод сначала во всех дочерних классах, а затем уже в родительских.
Пример вывода MRO (Method Resolution Order):
In : Child.__mro__
Out:
(__main__.Child,
__main__.Parent1,
__main__.Parent2,
__main__.GrandParent,
object)
👉@BookPython
Please open Telegram to view this post
VIEW IN TELEGRAM
👍5❤3
Прямой доступ к атрибутам объекта может быть не самой лучшей идеей. Если клиенты взаимодействуют с объектом через методы, вы всегда можете изменить способ обработки каждого запроса, в то время как при прямом доступе к атрибутам это может быть невозможно.
Разные языки решают эту проблему по-разному. В Ruby синтаксически невозможно получить прямой доступ к атрибуту:
Python предлагает решение, которое в некотором роде похоже на то, что есть в Ruby. Вы можете определить свойство (
📲 Мы в MAX
👉@BookPython
Разные языки решают эту проблему по-разному. В Ruby синтаксически невозможно получить прямой доступ к атрибуту:
obj.x — это вызов метода x. В Java рекомендуется делать все атрибуты приватными и писать тривиальные геттеры, например: public int getX() { return this.x; }.Python предлагает решение, которое в некотором роде похоже на то, что есть в Ruby. Вы можете определить свойство (
property), чтобы obj.x вызывал метод вместо прямого возврата атрибута x.
class Example:
def __init__(self, x):
self._x = x
@property
def x(self):
return self._x
👉@BookPython
Please open Telegram to view this post
VIEW IN TELEGRAM
👍2
С версии Python 3.0 выбрасывание исключения внутри блока
Результат выполнения:
Вы также можете добавить
Результат выполнения:
📲 Мы в MAX
👉@BookPython
except автоматически добавляет перехваченное исключение в атрибут __context__ нового исключения. Это приводит к тому, что оба исключения отображаются в traceback:
try:
1 / 0
except ZeroDivisionError:
raise ValueError('Zero!')
Результат выполнения:
Traceback (most recent call last):
File "test.py", line 2, in <module>
1 / 0
ZeroDivisionError: division by zero
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "test.py", line 4, in <module>
raise ValueError('Zero!')
ValueError: Zero!
Вы также можете добавить
__cause__ к любому исключению с помощью выражения raise ... from:
division_error = None
try:
1 / 0
except ZeroDivisionError as e:
division_error = e
raise ValueError('Zero!') from division_error
Результат выполнения:
Traceback (most recent call last):
File "test.py", line 4, in <module>
1 / 0
ZeroDivisionError: division by zero
The above exception was the direct cause of the following exception:
Traceback (most recent call last):
File "test.py", line 8, in <module>
raise ValueError('Zero!') from division_error
ValueError: Zero!
👉@BookPython
Please open Telegram to view this post
VIEW IN TELEGRAM
👍2
Профайлинг и Оптимизация Производительности
Когда ваш код уже не просто работает, а должен летать, на первый план выходит умение профилировать и оптимизировать производительность. Для Python это не просто трюки, а глубокое понимание CPython и его инструментов.
Шаг 1: Точное Измерение (Profiling)
Прежде чем оптимизировать, мы должны знать, где именно тратятся ресурсы. Слепое улучшение кода — это путь к бессмысленным изменениям и появлению новых багов.
- Модуль
- Line-by-line Profilers (
- Анализ Памяти (
Шаг 2: Реальная Оптимизация (Beyond Simple Fixes)
Найдя узкое место, приступаем к устранению, используя знания об устройстве Python.
1. Уменьшение Накладных Расходов Интерпретатора (Interpreter Overhead)
- Использование Встроенных Функций и Модулей C: Встроенные функции (например,
- Пример: Используйте
2. Манипуляции с Данными NumPy/Pandas
- Векторизация: Если вы работаете с числовыми данными, полностью переходите на NumPy и Pandas. Вместо циклов
3. Параллелизм vs. Конкурентность
- CPU-bound задачи (расчеты): Из-за GIL (Global Interpreter Lock) чистый Python не может эффективно использовать несколько ядер ЦП для одновременного выполнения кода на Python. Используйте модуль
- I/O-bound задачи (сеть, диск): Если код проводит много времени в ожидании (ввод-вывод), используйте конкурентность с помощью
📲 Мы в MAX
👉@BookPython
Когда ваш код уже не просто работает, а должен летать, на первый план выходит умение профилировать и оптимизировать производительность. Для Python это не просто трюки, а глубокое понимание CPython и его инструментов.
Шаг 1: Точное Измерение (Profiling)
Прежде чем оптимизировать, мы должны знать, где именно тратятся ресурсы. Слепое улучшение кода — это путь к бессмысленным изменениям и появлению новых багов.
- Модуль
cProfile: Стандартный и самый надежный инструмент для нахождения горячих точек (hotspots) — функций, где тратится больше всего времени. Он показывает совокупное время (tottime) и общее время (cumtime) выполнения каждой функции, включая вызовы извне.
import cProfile
import re
cProfile.run('re.compile("foo|bar")', filename='profile_data')
# Анализируем результаты
import pstats
p = pstats.Stats('profile_data')
p.sort_stats('cumulative').print_stats(10)
- Line-by-line Profilers (
line_profiler): Если cProfile показывает функцию, которая "тормозит", но вам нужно понять, какая именно строка внутри этой функции виновата, используйте внешние инструменты, такие как line_profiler.
# Декоратор @profile над нужной функцией
# Запуск: kernprof -l my_noscript.py
# Анализ: python -m line_profiler my_noscript.py.lprof
- Анализ Памяти (
memory_profiler): Для задач, связанных с большими данными или длительными процессами, где утечки памяти или излишнее потребление критичны, используйте memory_profiler или pympler.Шаг 2: Реальная Оптимизация (Beyond Simple Fixes)
Найдя узкое место, приступаем к устранению, используя знания об устройстве Python.
1. Уменьшение Накладных Расходов Интерпретатора (Interpreter Overhead)
- Использование Встроенных Функций и Модулей C: Встроенные функции (например,
sum, map, sorted) и функции из стандартной библиотеки, написанные на C (например, itertools, collections), работают значительно быстрее, чем их эквиваленты на чистом Python, поскольку избегают накладных расходов на GIL и байткод.- Пример: Используйте
collections.deque вместо list для быстрого добавления/удаления с обоих концов.2. Манипуляции с Данными NumPy/Pandas
- Векторизация: Если вы работаете с числовыми данными, полностью переходите на NumPy и Pandas. Вместо циклов
for в Python, обрабатывающих элементы по одному, используйте векторизованные операции. Это позволяет выполнять вычисления на уровне C/Fortran, эффективно используя процессор.3. Параллелизм vs. Конкурентность
- CPU-bound задачи (расчеты): Из-за GIL (Global Interpreter Lock) чистый Python не может эффективно использовать несколько ядер ЦП для одновременного выполнения кода на Python. Используйте модуль
multiprocessing для распараллеливания задачи между процессами.- I/O-bound задачи (сеть, диск): Если код проводит много времени в ожидании (ввод-вывод), используйте конкурентность с помощью
asyncio (асинхронный ввод-вывод) или threading. В этом случае GIL не мешает, так как Python "освобождает" его во время ожидания.👉@BookPython
Please open Telegram to view this post
VIEW IN TELEGRAM
👍3
В Python множества поддерживают операторы сравнения, где
Это означает, что множества частично упорядочены, то есть существуют такие
Некоторые функции, такие как
📲 Мы в MAX
👉@BookPython
a < b означает, что a является подмножеством b:
>>> {1} < {1, 2}
True
>>> {1} < {2, 3}
False
Это означает, что множества частично упорядочены, то есть существуют такие
a и b, что и a < b, и b < a — ложны:
>>> {1} < {2, 3}
False
>>> {1} > {2, 3}
False
Некоторые функции, такие как
min, max и sorted, требуют полного порядка, поэтому их применение к списку множеств может дать неожиданные результаты:
>>> min([{1}, {2}])
{1}
>>> min([{2}, {1}])
{2}
👉@BookPython
Please open Telegram to view this post
VIEW IN TELEGRAM
👍1
Иногда вам нужно очистить коллекцию в Python. Вы, вероятно, используете что-то вроде
Правильный способ очистки словаря, множества,
📲 Мы в MAX
👉@BookPython
d = {} (для словарей), но на самом деле это не очистка, а создание новой коллекции и выбрасывание старой. Это может сработать для вас, но другие владельцы того же объекта всё ещё будут иметь ссылку на оригинальный.Правильный способ очистки словаря, множества,
deque и других коллекций — вызвать x.clear(). 👉@BookPython
Please open Telegram to view this post
VIEW IN TELEGRAM
👍6
Иногда вам может понадобиться проверить синтаксис Python-файла без его запуска. Такая простая проверка может быть полезна, например, в качестве хука перед коммитом или быстрой проверки в рамках непрерывной интеграции (CI).
Прямого способа сделать это нет. Вы можете запустить файл с помощью команды
Тем не менее, стандартная библиотека Python содержит модуль
📲 Мы в MAX
👉@BookPython
Прямого способа сделать это нет. Вы можете запустить файл с помощью команды
python -m module.py, что предотвратит выполнение блока if __name__ == '__main__'. Однако все импорты всё равно будут выполнены, и это может привести к ошибкам, если вы хотите проверить синтаксис в среде, где модуль не может и не должен быть запущен.Тем не менее, стандартная библиотека Python содержит модуль
py_compile, который генерирует байт-код из исходного файла Python без его выполнения. Это именно то, что нам нужно:
$ python -m py_compile test.c
File "test.c", line 1
int main() {
^
SyntaxError: invalid syntax
👉@BookPython
Please open Telegram to view this post
VIEW IN TELEGRAM
❤2👍1
CPython поддерживает два уровня оптимизации. Вы можете включить их с помощью флагов
- Флаг
- Флаг
Обычная версия скрипта кэшируется в файл
📲 Мы в MAX
👉@BookPython
-O и -OO.- Флаг
-O устанавливает __debug__ в значение False и удаляет все операторы assert из программы. - Флаг
-OO делает то же самое, а также удаляет строки документации (docstrings).Обычная версия скрипта кэшируется в файл
.pyc, а оптимизированная версия раньше кэшировалась в файл .pyo. Однако, начиная с Python 3.5, файлы .pyo больше не используются. Вместо них, в соответствии с PEP 488, вводятся файлы .opt-1.pyc и .opt-2.pyc.👉@BookPython
Please open Telegram to view this post
VIEW IN TELEGRAM
👍3
«Reduce» — это функция высшего порядка, которая рекурсивно обрабатывает итерируемый объект, применяя некоторую операцию к следующему элементу и уже вычисленному значению. Также вы можете знать её под названиями «fold», «inject», «accumulate» или другими.
Использование
В Python функция
Также, если вам нужны простые лямбда-функции, такие как
📲 Мы в MAX
👉@BookPython
Использование
reduce с result = result + element даёт сумму всех элементов, result = min(result, element) возвращает минимум, а result = element позволяет получить последний элемент последовательности.В Python функция
reduce доступна (начиная с Python 3, она была перемещена в functools.reduce):
from functools import reduce
print(reduce(lambda s, i: s + i, range(10))) # 45
print(reduce(lambda s, i: min(s, i), range(10))) # 0
print(reduce(lambda s, i: i, range(10))) # 9
Также, если вам нужны простые лямбда-функции, такие как
lambda a, b: a + b, в Python есть модуль operator, который упрощает их использование:
from operator import add
print(reduce(add, range(10))) # 45
👉@BookPython
Please open Telegram to view this post
VIEW IN TELEGRAM
👍3❤1
Создание новой переменной в Python фактически означает создание нового имени для уже существующего объекта. Именно поэтому этот процесс называется связыванием имени (name binding).
Существует множество способов связать имя с объектом. Вот примеры того, как можно связать
Также можно привязать имя к объекту, манипулируя глобальным пространством имен:
Однако нельзя сделать то же самое с
📲 Мы в MAX
👉@BookPython
Существует множество способов связать имя с объектом. Вот примеры того, как можно связать
x:
x = y # Присваивание
import x # Импорт модуля
class x: pass # Определение класса
def x(): pass # Определение функции
def y(x): pass # Определение аргумента функции
for x in y: pass # Перебор элементов в цикле
with y as x: pass # Использование в конструкции with
except y as x: pass # Обработка исключения
Также можно привязать имя к объекту, манипулируя глобальным пространством имен:
In : x
NameError: name 'x' is not defined # Ошибка: переменная x не определена
In : globals()['x'] = 42 # Присваивание через globals()
In : x
Out: 42 # Теперь x привязан к 42
Однако нельзя сделать то же самое с
locals(), так как изменения словаря locals() игнорируются.👉@BookPython
Please open Telegram to view this post
VIEW IN TELEGRAM
👍4❤1
Когда в Python используется переменная, сначала она ищется в текущей области видимости. Если такая переменная не найдена, поиск продолжается во вложенной области. Это повторяется до тех пор, пока не будет достигнуто глобальное пространство имен.
Однако присваивание переменной работает иначе. Новая переменная всегда создается в текущей области видимости, если не указано
📲 Мы в MAX
👉@BookPython
x = 1
def scope():
x = 2
def inner_scope():
print(x) # выводит 2
inner_scope()
scope()
Однако присваивание переменной работает иначе. Новая переменная всегда создается в текущей области видимости, если не указано
global или nonlocal:
x = 1
def scope():
x = 2
def inner_scope():
x = 3
print(x) # выводит 3
inner_scope()
print(x) # выводит 2
scope()
print(x) # выводит 1
global позволяет использовать переменные из глобального пространства имен, а nonlocal ищет переменную в ближайшей окружающей области видимости. Сравните:
x = 1
def scope():
x = 2
def inner_scope():
global x
x = 3
print(x) # выводит 3
inner_scope()
print(x) # выводит 2
scope()
print(x) # выводит 3
x = 1
def scope():
x = 2
def inner_scope():
nonlocal x
x = 3
print(x) # выводит 3
inner_scope()
print(x) # выводит 3
scope()
print(x) # выводит 1
👉@BookPython
Please open Telegram to view this post
VIEW IN TELEGRAM
👍3
list позволяет хранить массив из любых объектов. Это довольно удобно, но может быть неэффективно. Для компактного представления массивов базовых значений можно использовать модуль array. Поддерживаемые значения включают различные типы C, такие как char, int, long, double и другие. Фактическое представление определяется реализацией C.
import array
a = array.array('B') # Создаем массив байтов
a.append(240)
a.append(159)
a.append(144)
a.append(180)
print(a.tobytes().decode('utf8')) # Выводит: '🐴'
👉@BookPython
Please open Telegram to view this post
VIEW IN TELEGRAM
👍6
Если вам нужно итерироваться по нескольким итерируемым объектам одновременно, функция
Обратите внимание, что
Для распаковки значений можно использовать оператор
📲 Мы в MAX
👉@BookPython
zip может быть хорошим выбором. Она возвращает генератор, который выдаёт кортежи, содержащие по одному элементу из каждого исходного итерируемого объекта:
In : eng = ['one', 'two', 'three']
In : ger = ['eins', 'zwei', 'drei']
In : for e, g in zip(eng, ger):
...: print('{e} = {g}'.format(e=e, g=g))
...:
one = eins
two = zwei
three = drei
Обратите внимание, что
zip принимает итерируемые объекты как отдельные аргументы, а не список аргументов. Для распаковки значений можно использовать оператор
*:
In : list(zip(*zip(eng, ger)))
Out: [('one', 'two', 'three'), ('eins', 'zwei', 'drei')]
👉@BookPython
Please open Telegram to view this post
VIEW IN TELEGRAM
👍1
Модуль
Эти два типа —
📲 Мы в MAX
👉@BookPython
io предоставляет два типа файловых объектов в памяти. Такие объекты могут быть полезны для работы с интерфейсами, которые поддерживают только файлы, без необходимости создавать их на диске. Очевидный пример — модульное тестирование.Эти два типа —
BytesIO и StringIO, которые работают соответственно с байтами и строками.
from io import StringIO
f = StringIO()
f.write('first\n') # Вывод: 6
f.write('second\n') # Вывод: 7
f.seek(0) # Вывод: 0
print(f.readline()) # Вывод: 'first\n'
print(f.readline()) # Вывод: 'second\n'
👉@BookPython
Please open Telegram to view this post
VIEW IN TELEGRAM
👍4❤1
Python поддерживает несколько способов запуска скрипта. Обычный вариант — это
Однако, можно также использовать
Можно также запустить Python с каталогом:
Пример:
📲 Мы в MAX
👉@BookPython
python foo.py; в этом случае foo.py просто выполняется.Однако, можно также использовать
python -m foo. Если foo — это не пакет, то foo.py ищется в sys.path и выполняется. Если это пакет, то Python сначала выполняет foo/__init__.py, а затем foo/__main__.py. Обратите внимание, что во время выполнения __init__.py значение __name__ равно foo, но во время выполнения __main__.py оно равно __main__.Можно также запустить Python с каталогом:
python dir/ или даже python dir.zip. В этом случае Python ищет dir/__main__.py и выполняет его, если находит.Пример:
$ ls foo
__init__.py __main__.py
$ cat foo/__init__.py
print(__name__)
$ cat foo/__main__.py
print(__name__)
$ python -m foo
foo
__main__
$ python foo/
__main__
$ python foo/__init__.py
__main__
👉@BookPython
Please open Telegram to view this post
VIEW IN TELEGRAM
👍4❤3👎1