Скрытые возможности Python [закрыто]
Описание проблемы
У меня возникла проблема с вопросом, который я нашел на StackOverflow. Он касается "малоизвестных, но полезных функций языка программирования Python". Однако, кажется, что данный вопрос имеет некоторые недостатки, которые мешают ему соответствовать формату Q&A на платформе:
Содержательное наполнение: В настоящее время вопрос не предлагает четкого контекста или целей. Он ожидает ответов, основанных на фактах, ссылках или экспертизе, но, вероятно, вызовет споры, обсуждения или опросы, а не целенаправленные указания.
Историческая значимость: Хотя вопрос может иметь историческое значение и интерес для сообщества, его содержание выходит за рамки того, что может быть полезно для новой аудитории.
Закрытие и блокировка: Вопрос был закрыт, и его невозможно обновить или переоткрыть, так как он помечен как «заблокированный». Это создает сложности для пользователей, которые ищут информацию о функциях Python.
Подход к улучшению
Я задумался, как можно улучшить этот вопрос или, возможно, создать новый, более актуальный, который соответствовал бы требованиям StackOverflow. Вот некоторые мысли:
Уточнить требования: Возможно, стоит сузить рамки до строго определенных функций Python и ввести критерии для ответов. Например, дать четкие рекомендации по описанию каждой функции и предоставлению примеров.
Пример формата: Создать формат, в котором пользователи могут легко вносить свою информацию, чтобы она была структурирована и полезна для других.
Обновление информации: Добавить возможность для сообщества активнее делиться малоизвестными, но полезными функциями, что могло бы стать плодотворной основой для будущих обсуждений.
Если есть дополнения или советы по этому вопросу, буду рад услышать ваш опыт.
5 ответ(ов)
Цепочка операторов сравнения:
>>> x = 5
>>> 1 < x < 10
True
>>> 10 < x < 20
False
>>> x < 10 < x*10 < 100
True
>>> 10 > x <= 9
True
>>> 5 == x > 4
True
Если вы думаете, что происходит сравнение 1 < x
, что дает True
, а затем сравнение True < 10
, что также True
, то нет, так не работает (посмотрите на последний пример). На самом деле это преобразуется в 1 < x and x < 10
, и x < 10 and 10 < x * 10 and x*10 < 100
, но с меньшим количеством написания, и каждая часть вычисляется только один раз.
Если вы пишете
x = (n for n in foo if bar(n))
вы создаете объект генератора и присваиваете его переменной x
. Теперь вы можете использовать его в цикле:
for n in x:
Преимущество этого подхода в том, что вам не требуется промежнительное хранение, которое было бы необходимо, если бы вы использовали списковое включение:
x = [n for n in foo if bar(n)]
В некоторых случаях это может привести к значительному ускорению выполнения.
Вы также можете добавлять множество условных операторов к генератору, тем самым фактически имитируя вложенные циклы:
>>> n = ((a, b) for a in range(0, 2) for b in range(4, 6))
>>> for i in n:
... print(i)
Вывод будет следующим:
(0, 4)
(0, 5)
(1, 4)
(1, 5)
Таким образом, использование генераторов может значительно повысить эффективность вашего кода, особенно при работе с большими объемами данных.
iter()
может принимать аргумент вызываемого (callable).
Например, рассмотрим следующий код:
def seek_next_line(f):
for c in iter(lambda: f.read(1), '\n'):
pass
Функция iter(callable, until_value)
многократно вызывает callable
и возвращает его результат до тех пор, пока не будет получено значение until_value
. В данном случае мы используем анонимную функцию (лямбда), которая читает по одному символу из файла f
, пока не встретится символ новой строки ('\n'
). Как только будет прочитан символ '\n'
, цикл завершится.
Будьте осторожны с изменяемыми значениями по умолчанию
Когда вы используете изменяемые объекты, такие как списки или словари, в качестве значений по умолчанию для аргументов функции, это может привести к неожиданным проблемам. Рассмотрим следующий пример:
>>> def foo(x=[]):
... x.append(1)
... print(x)
...
>>> foo()
[1]
>>> foo()
[1, 1]
>>> foo()
[1, 1, 1]
Вы можете заметить, что при каждом вызове функции foo
к списку, переданному в качестве значения по умолчанию, добавляется 1
. В результате список x
сохраняет свое состояние между вызовами, что обычно не является желаемым поведением.
Вместо этого рекомендуется использовать отправное значение (sentinel value), которое будет обозначать "не задано", и затем инициализировать изменяемый объект внутри функции:
>>> def foo(x=None):
... if x is None:
... x = []
... x.append(1)
... print(x)
>>> foo()
[1]
>>> foo()
[1]
В этом примере, если аргумент x
не передан, он инициализируется пустым списком, и каждый вызов функции будет использовать новый список, что позволит избежать накопления значений из предыдущих вызовов.
Если вам не нравится использовать пробелы для обозначения областей видимости, вы можете воспользоваться фигурными скобками в стиле C, выполнив:
from __future__ import braces
Однако стоит отметить, что это приведет к возникновению исключения SyntaxError
, поскольку данная конструкция на самом деле предназначена для демонстрации того, что использование фигурных скобок в Python будет невозможно. Таким образом, вам все же придется следовать правилам языка и использовать пробелы.
Вызов функции модуля по его имени (строке)
Как напечатать без новой строки и пробела
Изменение типа столбца в pandas
Что такое __pycache__?
Как заполнить строку в Python пробелами?