106 подписчиков
🖥 Необычные фишки Python.
1. Есть оператор “else”, но нет “if”
В Python можно использовать оператор “else” без “if”.
leaders = ["Elon", "Tim", "Warren"]
for i in leaders:
if i == "Yang":
print("Yang is a leader!")
break
else:
print("Not found Yang!")
2. Изменение неизменяемого кортежа
tp = ([1, 2, 3], 4, 5)
tp[0].append(4)
print(tp)
# ([1, 2, 3, 4], 4, 5)
Это происходит потому, что изменяемость вложенных объектов Python зависит от каждого объекта. tp — неизменяемый кортеж, но первый элемент tp — список, который является изменяемым.
3. 256 — это 256, но 257 — не 257
Иногда результаты при проверке на равенство чисел в Python могут удивить:
>>> a=256
>>> b=256
>>> a is b
True
>>> x=257
>>> y=257
>>> x is y
False
Для экономии времени и затрат памяти Python предварительно загружает все малые целые числа в диапазоне [-5, 256]. Поэтому, когда объявляется целое число в этом диапазоне, Python просто ссылается на кэшированное целое число и не создает новый объект.
a и b — один и тот же объект, но x и y — два разных объекта.
Чтобы убедиться в этом, выведем id каждой переменной:
>>> id(a)
1696073345424
>>> id(b)
1696073345424
>>> id(x)
1696122928496
>>> id(y)
1696122928752
Этот механизм называется интернированием целых чисел или кэшированием целых чисел.
Но что выведет следующий код? Снова False?
>>> 257 is 257
Python всегда старается сделать все возможное, чтобы сохранить ясность. Поскольку две переменные не были определены отдельно, Python получит достаточно контекста в рамках однострочной команды и на этот раз выведет True.
4. Интернирование строк
Подобно механизму интернирования целых чисел, Python также кэширует строки небольшого размера для экономии вычислительных ресурсов.
Рассмотрим пример:
>>> a = "Yang"
>>> b = "Yang"
>>> a is b
True
>>> c = "Yang Zhou"
>>> d = "Yang Zhou"
>>> c is d
False
Для приведенного выше примера был использован CPython с алгоритмом кэширования AST optimizer. Этот алгоритм может кэшировать до 4096 символов, но строки, включающие пробелы, не будут интернированы.
5. 0,1+0,2 — это не 0,3
Все знают, что 0,1+0,2 равно 0,3, но Python так не считает:
print(0.1+0.2==0.3)
# False
Каков же результат вычисления 0,1+0,2 в Python, если не 0,3?
print(0.1+0.2)
# 0.30000000000000004
По правде говоря, это не вина Python. Ни один компьютер не может точно вычислить плавающее значение.
6. “+=” быстрее, чем “=”
При конкатенации строк в Python операторы += и + могут дать один и тот же результат, но с разными временными затратами:
import timeit
print(timeit.timeit("s1 = s1 + s2 + s3", setup="s1 = ' ' * 100000; s2 = ' ' * 100000; s3 = ' ' * 100000", number=100))
# 0.7268792000000001
print(timeit.timeit("s1 += s2 + s3", setup="s1 = ' ' * 100000; s2 = ' ' * 100000; s3 = ' ' * 100000", number=100))
# 0.3451913999999999
При конкатенации более двух строк в Python оператор += быстрее, чем +. Поскольку += — это операция in-place (на месте), время на создание нового объекта будет сэкономлено по сравнению с операцией +.
7. Три точки
Если вам потребуется заполнитель для Python-функции, вы, скорее всего, воспользуетесь ключевым словом pass:
def my_func():
pass
Но есть и другой способ сделать это:
def my_func():
...
8. Оператор “with”
Ни в одном другом языке программирования нет такого оператора, поэтому он удивляет начинающих в Python.
with open("test.txt",'w') as f:
f.write("Yang is writing!")
Оператор “with” — это синтаксический сахар для управления контекстом. Используя его, вы можете не прописывать явно функцию close() для закрытия файла, поскольку он будет закрыт автоматически после использования.
9. Префиксные операторы * и **
При чтении проектов Python с открытым исходным кодом вам, вероятно, неоднократно встречался следующий стиль определения функции:
def func(*args, **kwargs):
pass
Что означают эти странные звездочки?
Параметр с префиксом * может собрать любое количество позиционных аргументов в tuple.
C помощью звездочек можно производить распаковку итерируемых переменных
3 минуты
2 июля 2023
117 читали