In:
Out:
Цифры 0 1 2 3 4 5 6 7 8 9 — это не единственные символы, которые считаются цифрами. Python следует правилам Unicode и считает «цифрами» сотни различных символов. Вот полный список таких символов.
Это влияет на такие функции, как
👉@BookPython
int('୧৬𝟙༣')
Out:
1613
Цифры 0 1 2 3 4 5 6 7 8 9 — это не единственные символы, которые считаются цифрами. Python следует правилам Unicode и считает «цифрами» сотни различных символов. Вот полный список таких символов.
Это влияет на такие функции, как
int
, unicode.isdecimal
и даже re.match
:
# Пример 1
int('෯')
# Вывод:
9
# Пример 2
'٢'.isdecimal()
# Вывод:
True
# Пример 3
import re
bool(re.match(r'\d', '౫'))
# Вывод:
True
👉@BookPython
>>> bool(datetime(2018, 1, 1).time())
False
>>> bool(datetime(2018, 1, 1, 13, 12, 11).time())
True
До Python 3.5 объекты
datetime.time()
считались ложными, если они представляли полночь по UTC. Это могло приводить к трудноуловимым ошибкам. В следующих примерах if not
может выполниться не потому, что created_time
равен None
, а потому, что время — полночь.
def create(created_time=None) -> None:
if not created_time:
created_time = datetime.now().time()
Можно исправить это, явно проверяя на
None
:
def create(created_time=None) -> None:
if created_time is None:
created_time = datetime.now().time()
👉@BookPython
Please open Telegram to view this post
VIEW IN TELEGRAM
В Python нет поддержки асинхронных операций с файлами. Чтобы сделать их неблокирующими, нужно использовать отдельные потоки.
Для асинхронного выполнения кода в потоке следует использовать метод
Сторонний модуль aiofiles делает всё это за тебя, предоставляя простой и удобный интерфейс:
👉@BookPython
Для асинхронного выполнения кода в потоке следует использовать метод
loop.run_in_executor
.Сторонний модуль aiofiles делает всё это за тебя, предоставляя простой и удобный интерфейс:
async with aiofiles.open('filename', mode='r') as f:
contents = await f.read()
👉@BookPython
Иногда нужно создать функцию на основе более универсальной.
Например, у функции
Это полезно, когда нужно передать функцию как аргумент другой, более общей функции, но при этом некоторые аргументы должны быть зафиксированы:
Без
👉@BookPython
Например, у функции
int()
есть параметр base
, который мы хотим зафиксировать, чтобы получить новую функцию base2
:
>>> int("10")
10
>>> int("10", 2)
2
>>> def base2(x):
... return int(x, 2)
...
>>> base2("10")
2
functools.partial
позволяет сделать то же самое, но точнее и семантически понятнее:
base2 = partial(int, base=2)
Это полезно, когда нужно передать функцию как аргумент другой, более общей функции, но при этом некоторые аргументы должны быть зафиксированы:
>>> map(partial(int, base=2), ["1", "10", "100"])
[1, 2, 4]
Без
partial
пришлось бы делать так:
>>> map(lambda x: int(x, base=2), ["1", "10", "100"])
[1, 2, 4]
👉@BookPython
Please open Telegram to view this post
VIEW IN TELEGRAM
Существует две встроенные функции, которые позволяют анализировать итерируемые объекты без необходимости писать тривиальные и избыточные циклы
Обе функции особенно полезны в сочетании со списковыми включениями (list comprehensions):
Функции
👉@BookPython
for
. Это all
и any
.any
возвращает True
, если хотя бы одно значение истинно; all
возвращает True
, только если все значения истинны. Для пустого итерируемого объекта all
возвращает True
, а any
— False
.Обе функции особенно полезны в сочетании со списковыми включениями (list comprehensions):
package_broken = any(
part.is_broken() for part in package.get_parts()
)
package_ok = all(
part.ok() for part in package.get_parts()
)
Функции
any
и all
зачастую взаимозаменяемы благодаря законам де Моргана. Используй ту, с которой код будет понятнее.👉@BookPython
Если ты хочешь, чтобы у объектов класса автоматически увеличивался ID, это можно реализовать, отслеживая текущий ID в атрибуте класса:
Обрати внимание, что нельзя использовать
Лучше использовать фабричный метод вместо
Эта версия также проще для тестирования, так как можно легко задать любой ID вручную.
👉@BookPython
class Task:
_task_id = 0
def __init__(self):
self._id = self._task_id
type(self)._task_id += 1
Обрати внимание, что нельзя использовать
self._task_id += 1
— это создаст атрибут _task_id
внутри экземпляра, а не изменит значение на уровне класса.Лучше использовать фабричный метод вместо
__init__
, чтобы код выглядел аккуратнее:
class Task:
_task_id = 0
def __init__(self, task_id):
self._id = task_id
@classmethod
def create(cls):
obj = cls(cls._task_id)
cls._task_id += 1
return obj
Эта версия также проще для тестирования, так как можно легко задать любой ID вручную.
👉@BookPython
17 июня(уже завтра!) в 19:00 по мск приходи онлайн на открытое собеседование, чтобы посмотреть на настоящее интервью на Middle Python-разработчика.
Как это будет:
Это бесплатно. Эфир проходит в рамках менторской программы от ШОРТКАТ для Java-разработчиков, которые хотят повысить свой грейд, ЗП и прокачать скиллы.
Переходи в нашего бота, чтобы получить ссылку на эфир → @shortcut_py_bot
Реклама. ООО "ШОРТКАТ", ИНН: 9731139396, erid: 2VtzqubLfbk
Please open Telegram to view this post
VIEW IN TELEGRAM