Выражение присваивания (также известное как оператор walrus) — это функциональность, которая появилась в Python недавно, в версии 3.8. Однако применение walrus является предметом дискуссий и множество людей испытывают безосновательную неприязнь к нему.
Под катом эксперт компании IBM Мартин Хайнц*, разработчик и DevOps-инженер, постарается убедить вас в том, что оператор walrus — действительно хорошее дополнение языка. И его правильное использование поможет вам сделать код более лаконичным и читаемым.
*Обращаем ваше внимание, что позиция автора может не всегда совпадать с мнением МойОфис.
Рассмотрим основы
Если вы вдруг не знакомы с моржовым оператором :=
(walrus), давайте для начала рассмотрим некоторые основные случаи его использования.
В первом примере я покажу вам, как можно использовать оператор walrus, чтобы сократить количество вызовов функции.
Давайте представим функцию func()
, которая производит какие-то очень ресурсоемкие расчеты. Она требует много времени для вычисления результатов, поэтому мы не хотим вызывать ее многократно:
# "func" вызывает трижды
result = [func(x), func(x)**2, func(x)**3]
# Переиспользуем результат функции без разделения кода на несколько строк
result = [y := func(x), y**2, y**3]
В первой форме объявления списка, func(x)
вызывается трижды, каждый раз возвращая один и тот же результат, который каждый раз тратил ресурсы вычислительной машины. Когда мы перепишем выражение с использованием оператора walrus, func()
будет вызвана только один раз, присваивая результат вычисления y
и повторно используя значение для оставшихся двух элементов списка. Вы можете сказать "Просто добавь y = func(x)
перед объявлением списка и тебе не понадобится оператор walrus!". Можно так сделать, но для этого потребуется еще одна дополнительная строка кода и, на первый взгляд, без знания о том, что func(x)
очень медленная, может быть неясно, зачем эта переменная нужна.
Если первый пример не убедил вас, вот еще один. Рассмотрим следующие способы объявления списка тоже с ресурсоемкой func()
:
result = [func(x) for x in data if func(x)]
result = [y for x in data if (y := func(x))]
В первой строке func(x)
вызывается дважды в каждой итерации. Альтернатива — использовать оператор walrus. Значение рассчитывается однократно — в условном выражении, и используется повторно. Размер кода тот же, обе строки одинаково читаемые, но на второй строке реализация в два раза эффективнее. Вы можете избежать применения :=
с сохранением эффективности исполняемого кода путем описания конструкции через обычный цикл, однако для этого потребуется 5 строк кода.
Одно из наиболее типовых применений оператора walrus — в сокращении количества излишних условий, таких как найденные соответствия при использовании регулярных выражений.
import re
test = "Something to match"
pattern1 = r"^.*(thing).*"
pattern2 = r"^.*(not present).*"
m = re.match(pattern1, test)
if m:
print(f"Matched the 1st pattern: {m.group(1)}")
else:
m = re.match(pattern2, test)
if m:
print(f"Matched the 2nd pattern: {m.group(1)}")
# ---------------------
# Или иначе
if m := (re.match(pattern1, test)):
print(f"Matched 1st pattern: '{m.group(1)}'")
elif m := (re.match(pattern2, test)):
print(f"Matched 2nd pattern: '{m.group(1)}'")
Используя walrus мы сократили один и тот же код с 7 до 4 строк, сделав его более читаемым через удаление ненужных if
.
Следующий пример — это так называемая идиома "loop-and-half":
while True: # Loop
command = input("> ")
if command == 'exit': # And a half
break
print("Your command was:", command)
# ---------------------
# Или иначе
while (command := input("> ")) != "exit":
print("Your command was:", command)
Обычное решение заключается в использовании бесконечного цикла, в котором управление циклом осуществляется через объявление break
. Вместо этого мы можем задействовать оператор walrus, чтобы заново присвоить значение исполненной команды и затем использовать его в условии остановки цикла на той же строке, делая код более явным и коротким.
Простое упрощение может быть применено также к другому циклу, while
— например, в случае чтения файлов построчно или получения данных из сокета.
Суммирование данных прямо на месте
Обратимся к более продвинутым примерам использования оператора walrus. В этот раз рассмотрим возможность суммирования данных прямо по месту применения:
data = [5, 4, 3, 2]
c = 0; print([(c := c + x) for x in data]) # c = 14
# [5, 9, 12, 14]
from itertools import accumulate
print(list(accumulate(data)))
# ---------------------
data = [5, 4, 3, 2]
print(list(accumulate(data, lambda a, b: a*b)))
# [5, 20, 60, 120]
a = 1; print([(a := a*b) for b in data])
# [5, 20, 60, 120]
В первых двух строках показано, как можно использовать walrus для расчета суммы значений. В этом простом случае функция accumulate
лучше подходит для этой цели (как видно из следующих двух строк). Однако применение itertools
с увеличением сложности и объема кода делает его менее читаемым и, по моему мнению, версия с :=
намного приятнее, чем с lambda
.
Если вы все еще не убеждены, посмотрите сводные примеры в документации (например, сложный процент или логистическую карту): они не выглядят читаемыми. Попробуйте переписать их на использование выражения присваивания :=
, и они будут смотреться намного лучше.
Именованные значения в f-string
Этот пример показывает возможные случаи и ограничения использования :=
в сравнении с лучшими практиками.
Если хотите, то можете использовать оператор walrus в f-string:
from datetime import datetime
print(f"Today is: {(today:=datetime.today()):%Y-%m-%d}, which is {today:%A}")
# Today is: 2022-07-01, which is Friday
from math import radians, sin, cos
angle = 60
print(f'{angle=}\N{degree sign} {(theta := radians(angle)) =: .2f}, {sin(theta) =: .2f}, {cos(theta) =: .2f}')
# angle=60° (theta := radians(angle)) = 1.05, sin(theta) = 0.87, cos(theta) = 0.50
В первом выражении print
используется :=
для определения переменной today
, которая затем повторно используется на той же строке, предотвращая повторный вызов функции datetime.today()
.
Похожим образом во втором примере объявлена theta
переменная, которая затем используется снова для расчета sin(theta)
и cos(theta)
. В данном случае в выражении также встречается сочетание символов, которое выглядит как "обратный" walrus. Символ =
отвечает за вывод выражения на экран, а в связке с :
используется для форматированного вывода значения выражения.
Заметим также, что выражение с оператором walrus требует обрамления в скобки, чтобы внутри f-string оно интерпретировалось корректно.
Any и ALL
Можно использовать функции any()
и all()
для проверки удовлетворения условию любых или всех значений в итерируемом объекте. А что, если вы захотите также значение, которое оставляет any()
для возвращаемого значения True
(так называемый "свидетель") или же значение, которое не удовлетворило проверке all()
(так называемый "контрпример")?
numbers = [1, 4, 6, 2, 12, 4, 15]
# Возвращает только результат логического выражения, не значение
print(any(number > 10 for number in numbers)) # True
print(all(number < 10 for number in numbers)) # False
# ---------------------
any((value := number) > 10 for number in numbers) # True
print(value) # 12
all((counter_example := number) < 10 for number in numbers) # False
print(counter_example) # 12
Обе функции any()
и all()
используют короткую схему вычисления результата. Это означает, что они остановят вычисление, как только найдут первого "свидетеля" или "контрпример". Поэтому переменная, созданная с помощью оператора walrus, всегда будет давать нам первого "свидетеля"/"контрпример".
Подводные камни и ограничения
Ранее в тексте я пытался мотивировать вас использовать оператор walrus. Полагаю, важно также предупредить о некоторых недостатках и ограничениях в отношении этого оператора.
В предыдущем примере было показано, что короткая схема может быть полезна для захвата значений в any()
/all()
, но в некоторых случаях это может привести к неожиданным результатам:
for i in range(1, 100):
if (two := i % 2 == 0) and (three := i % 3 == 0):
print(f"{i} is divisible by 6.")
elif two:
print(f"{i} is divisible by 2.")
elif three:
print(f"{i} is divisible by 3.")
# NameError: name 'three' is not defined
Во фрагменте выше приведено условное выражение с 2 объединенными присваиваниями, проверяющими, на сколько делится число — на 2, 3 или 6 в порядке очередности (если условие 1 верно, то 2 и 3 тоже верно). На первый взгляд это может казаться интересным трюком, но благодаря короткой схеме вычисления, если выражение (two := i % 2 == 0
) будет неверным, то следующее условие будет пропущено, а переменные останутся не определены или будут иметь неактуальные значения от предыдущей итерации.
Короткая схема вычисления логического выражения все же может быть выгодной/намеренной. Например, можно ее использовать с регулярными выражениями для поиска соответствия нескольким шаблонам в строке:
import re
tests = ["Something to match", "Second one is present"]
pattern1 = r"^.*(thing).*"
pattern2 = r"^.*(present).*"
for test in tests:
m = re.match(pattern1, test)
if m:
print(f"Matched the 1st pattern: {m.group(1)}")
else:
m = re.match(pattern2, test)
if m:
print(f"Matched the 2nd pattern: {m.group(1)}")
# Соответствие первому шаблону: thing
# Соответствие второму шаблону: present
for test in tests:
if m := (re.match(pattern1, test) or re.match(pattern2, test)):
print(f"Matched: '{m.group(1)}'")
# Соответствие: 'thing'
# Соответствие: 'present'
Мы уже рассматривали версию этого фрагмента в разделе «Рассмотрим основы», где использовали if
/elif
вместе с оператором walrus. Здесь же представлено упрощение через схлопывание условия в один if
.
Если вы только познакомились с оператором walrus, то можете заметить, что он заставляет область видимости переменных вести себя иначе в list
comprehensions.
values = [3, 5, 2, 6, 12, 7, 15]
tmp = "unmodified"
dummy = [tmp for tmp in values]
print(tmp)
# Как ожидалось, переменная "tmp" не была переопределена.
# Она по-прежнему имеет привязку к значению "unmodified"
total = 0
partial_sums = [total := total + v for v in values]
print(total) # 50
С использованием обычных list
/dict
/set
comprehensions, область видимости переменной цикла остается внутри конструкции и, следовательно, любая существующая переменная с тем же именем останется неизменной. Однако с использованием оператора walrus, переменная из comprehension total
остается доступной после вычисления значения конструкции, получая присвоенное значение внутри comprehension.
Когда использование walrus в коде становится более удобным для вас, вы можете попробовать использовать его в других случаях. Но есть один случай, в котором вам не удастся его использовать — выражения с with
(менеджером контекста):
class ContextManager:
def __enter__(self):
print("Entering the context...")
def __exit__(self, exc_type, exc_val, exc_tb):
print("Leaving the context...")
with ContextManager() as context:
print(context) # None
with (context := ContextManager()):
print(context) # <__main__.ContextManager object at 0x7fb551cdb9d0>
Когда мы используем обычный синтаксис with ContextManager() as context: ...
, контекст привязывается к возвращаемому значению context.enter()
, тогда же как при использовании версии с :=
происходит связь с результатом самого ContextManager()
. Зачастую это не важно, потому что context.enter()
обычно возвращает self
, но в случае, если это не так, будет крайне сложно отладить проблему.
Для более практического примера рассмотрим ниже, что происходит при использовании оператора walrus с контекстным менеджером closing
:
from contextlib import closing
from urllib.request import urlopen
with closing(urlopen('https://www.python.org')) as page:
for line in page:
print(line) # Выводится вебсайт в формате HTML
with (page := closing(urlopen('https://www.python.org'))):
for line in page:
print(line) # TypeError: 'closing' object is not iterable
Еще одна проблема, с которой вы можете столкнуться — относительный приоритет :=
, который ниже, чем другие логические операторы:
text = "Something to match."
flag = True
if match := re.match(r"^.*(thing).*", text) and flag:
print(match.groups()) # AttributeError: 'bool' object has no attribute 'group'
if (match := re.match(r"^.*(thing).*", text)) and flag:
print(match.groups()) # ('thing',)
Здесь нам нужно обрамлять выражение присваивания в скобки для обеспечения гарантии, что результат re.match(...)
будет записан в переменную. Если мы этого не сделаем, выражение and
будет рассчитано в первую очередь и переменной будет присвоен логический результат выражения.
И наконец, есть некоторая ловушка или скорее легкое ограничение. В данный момент нельзя использовать аннотации типов на той же строке с оператором walrus. Следовательно, если вы хотите определить тип переменной, то выражение следует разделить на 2 строки:
from typing import Optional
value: Optional[int] = None
while value := some_func():
... # Описание действия
Заключительные мысли
Как в случае с любой особенностью синтаксиса языка, злоупотребление оператором walrus может привести к ухудшению ясности и читаемости кода. Не следует внедрять его в коде при каждом удобном случае. Воспринимайте этот оператор как инструмент — будьте осведомлены о его преимуществах и недостатках и используйте его там, где это уместно.
Если хотите ознакомиться с большим количеством практических использований оператора walrus, сверьтесь с его представлением в стандартной библиотеке CPython — все изменения могут быть найдены в этом PR.
Кроме того, я также рекомендую прочитать PEP 572: в нем содержится еще больше примеров, а также обоснование внедрения оператора в стандартную библиотеку.
Комментарии (46)
bret99
15.09.2022 13:08+31Опять про моржа...Кому как, но субъективно укорочение кода нередко приводит к его нечитабельности. Вопрос, надо ли приносить операторы из других языков для того, чтобы "стильно, модно, молодежно", с очень сомнительным выигрышем в производительности (он вообще есть..?), остается открытым и делом вкусовщины.
vadimr
15.09.2022 13:09оператор Walrus
Уж или “моржовый оператор”, или “оператор :=”. Это google translate, что ли?
IvanSTV
15.09.2022 13:19-13извините за офтоп, а почему сотрудник компании МойОфис кодит на питоне, а компания в продукт в качестве языка макросов воткнула ублюдочный LUA?
trinxery
15.09.2022 13:44+13Как язык, часто применяемый как раз для скриптинга внутри приложений. Чтобы не тащить немаленький питон или любой другой язык, и для своей роли выглядит он вполне неплохо
IvanSTV
15.09.2022 13:54-6и что ж там неплохого? То, что делалось в VBA на 5 строчек стало 20?
Плюс IDE встроенный в мойофис абсолютно ублюдочный. Макрорекордер не только не помогает, но еще больше запутывает. Я понимаю, что у кого-то здесь реклама и я не в кассу со своими претензиями. Но доколе?
Про питон. Сейчас нет нужды тащить его немаленький весь и целиком. Достаточно обеспечить базовый функционал и дальше подключить кастомные библиотеки, Да и того... у меня на ноуте терабайт. Я себе для табличного анализа и питон поставлю. и все остальное. Табличный анализ - он не делается на печатной машинке. Аргументы про размер так себе.
trinxery
15.09.2022 14:07+9Плюс IDE встроенный в мойофис абсолютно ублюдочный
Если IDE плохая, то она будет такой и с питоном, и с lua
Сейчас нет нужды тащить его немаленький весь и целиком. Достаточно обеспечить базовый функционал
И какие же части стандартной библиотеки нам оставить, а какие выпилить? И это будет уже не чистый питон, что создаёт ситуации когда человек пишет на питоне обыкновенном а почему-то код не работает
Да и того... у меня на ноуте терабайт
(так и хочется написать "из-за таких как вы у нас калькуляторы на электроне") В конце концов "мойофис" создан в первую очередь для госконтор с госкомпами, которые к печатной машинке обычно ближе, чем к ноуту "с терабайтом"
IvanSTV
15.09.2022 14:24-6И какие же части стандартной библиотеки нам оставить, а какие выпилить? И это будет уже не чистый питон, что создаёт ситуации когда человек пишет на питоне обыкновенном а почему-то код не работает
в VBA именно так относительно VB, и никаких проблем не было
Если IDE плохая, то она будет такой и с питоном, и с lua
IDE усиливает ублюдочность Lua
В конце концов "мойофис" создан в первую очередь для госконтор с госкомпами, которые к печатной машинке обычно ближе, чем к ноуту "с терабайтом"
В таком случае компании надо определиться, то ли они делают софт для печатных машинок. то ли они делают полноценный офисный продукт. А то везде дуют в уши, что полноценный продукт, а реально продукт неполноценный. Но даже не в этом дело - нет даже понимания собственной ущербности, и, соответственно, не видно желания как-то исправлять.
trinxery
15.09.2022 14:44+6в VBA именно так относительно VB, и никаких проблем не было
Сомневаюсь, что из VB вообще можно было много урезать, а питон мы берём в частности и из-за его обширной стандартной библиотеки
ублюдочность Lua
О вкусах не спорят, все дела (но тогда и не стоит во второй раз упоминать "ублюдочность"), но, имхо, Луа нормально выглядит; может быть стоит убрать остатки паскаля в виде begin/end, но проще уж оставить стандартный Луа
В таком случае компании надо определиться, то ли они делают софт для
печатных машинок. то ли они делают полноценный офисный продукт. А то
везде дуют в уши, что полноценный продукт, а реально продукт
неполноценный.Когда-то мне приходилось сидеть за нетбуком с двумя гигами рамы. Линукс работает нормально, винда - нет. Firefox работает неплохо, хром - нет. Все четверо - полноценные продукты, но некоторые работают на "печатной машинке", некоторые нет
Но даже не в этом дело - нет даже понимания собственной ущербности, и, соответственно, не видно желания как-то исправлять.
Пользовались "Мойофисом"? Я - нет, но я как-то и не слышал заявлений прямо об "ущербности" продукта. Да, недоработки есть, функционал неполный, но всё же, или вывод сделан только по причине использования Lua?
IvanSTV
15.09.2022 16:32а питон мы берём в частности и из-за его обширной стандартной библиотеки
по размеру стандартная библиотека не больше стандартной для VBA. И десятки лет те же госконторы пользовались и претензий о размерах не высказывали. В мелкософтах сейчас в принципе размеры такие, что туда-сюда гигабайт-не велика проблема. И всегда так было, соразмерно масштабам. Выбор именно этого языка - это попытка подмять разработку пользовательских приложений под себя или просто продекларировать, наличие при фактическом отсутствии?
Lua не позволяет полноценно автоматизировать и закрывать отсутствующие функции. Повторяю, язык, в отличие от VBA не развит, объектная база скудная, стандартные библиотеки скудные. Прочитал инструкцию по Lua и охренел, потому что простое изменение шрифта в выделении превращается в квест.
Все четверо - полноценные продукты, но некоторые работают на "печатной машинке", некоторые нет
МойОфис не сильно экономит память и ресурсы, да. поменьше мелкософтов, но функционал тоже пропорционально меньше. Про полноценность я бы не говорил, потому что стандартных инструментов мало, и поддержки макросов фактически тоже нет: язык и IDE к пользователю недружелюбны по максимуму, а некоторые вещи вообще нереализуемы (по крайней мере, из того, что я прочитал). Какая мне разница, если я сильно теряю в функционале, переходя на него?
Пользовались "Мойофисом"? Я - нет, но я как-то и не слышал заявлений прямо об "ущербности" продукта.
перед глазами, ради тестирования. Как бы нехилый вызов - переписать всю свою кучу примочек и костылей с VBA на Lua при том. что инструмент не позволяет толком обратиться с ячейке без реверансов.
trinxery
15.09.2022 16:53+3по размеру стандартная библиотека не больше стандартной для VBA
я не спец в VBA, вы не спец в питоне, но я слышал как о с.б. питона отзываются как о [чуть ли не] мощнейшей среди всех языков вообще.
И десятки лет те же госконторы пользовались и претензий о размерах не высказывали. В мелкософтах сейчас в принципе размеры такие, что туда-сюда гигабайт-не велика проблема.
в условном "офисе 2007", да, размеры будут поменьше (предвещая ответ: да, точно есть места с относительно новым пакетом софта, но мест с софтом старым гораздо больше)
просто продекларировать, наличие при фактическом отсутствии
то есть для вас ни один встраиваемый язык кроме VBA за язык и не считается?
Lua не позволяет полноценно автоматизировать и закрывать отсутствующие функции. Повторяю, язык, в отличие от VBA не развит, объектная база скудная, стандартные библиотеки скудные.
Потому что это встраиваемый язык. Окружение должно предоставлятся программой
Прочитал инструкцию по Lua и охренел, потому что простое изменение шрифта в выделении превращается в квест.
Вопросы к авторам софта, не к Луа. И VBA можно в такое превратить, только майкрософт предоставили нормальное окружение, в отличие от авторов мойофиса. Условный доступ к ячейке или что угодно ещё для взаимодействия с продуктом - зона ответственности не Луа, а разработчиков этого самого продукта.
Про полноценность я бы не говорил, потому что стандартных инструментов мало, и поддержки макросов фактически тоже нет: язык и IDE к пользователю недружелюбны по максимуму, а некоторые вещи вообще нереализуемы (по крайней мере, из того, что я прочитал). Какая мне разница, если я сильно теряю в функционале, переходя на него?
Опять история про окружение и суть встраиваемых языков. Такие языки должны предоставлять основные функции и возможности собственного расширения.
Как бы нехилый вызов - переписать всю свою кучу примочек и костылей с VBA на Lua
С Lua на VBA не лучше
при том. что инструмент не позволяет толком обратиться с ячейке без реверансов.
см. пункты про "окружение"
IvanSTV
15.09.2022 17:32я не спец в VBA, вы не спец в питоне, но я слышал как о с.б. питона отзываются как о [чуть ли не] мощнейшей среди всех языков вообще.
у меня и то, и то на ноуте. По размерам ничего страшного. если бы вместо Lua взяли питон, например. Апелляция к размеру несостоятельна.
в условном "офисе 2007", да, размеры будут поменьше (предвещая ответ: да, точно есть места с относительно новым пакетом софта, но мест с софтом старым гораздо больше)
там, где требуется серьезный анализ данных, соотношение обратное. Да и откуда статистика-то? 2007 активно заменялся - прошло 15 лет. Я его даже когда фрилансил на VBA не видел ни разу.
Вопросы к авторам софта, не к Луа.
зона ответственности не Луа, а разработчиков этого самого продукта.
вот я и задаю вопросы к авторам софта в первую очередь. Авторам Луа во вторую, потому что в дополнение и сам язык недружелюбен к юзеру - много излишнего синтаксиса, нет многих методов, которые в других языках есть, например. Но главный вопрос ко всем - какого хера?
Lua специфичен как внутренний язык для тех программ. где требуется КВАЛИФИЦИРОВАННАЯ ДОРАБОТКА ПОД ПОЛЬЗОВАТЕЛЯ. А в качестве языка массового пользования с низким порогом он абсолютно непригоден - все, вываливающееся за пределы куцего набора встроенных функций и операторов, выполняется через C API. Есть разница между - у меня замначальника склада с помощью макрорекордера, гугла и какой-то матери в экселе накропал форму для проверки инвентаризаций и я судорожно ищу, где бы мне нанять фрилансера, чтобы накропал на склад форму для проверки инвентаризаций, потому что мне некогда, а мужик никогда не разберется с этой хренью, особенно с API даже если его накачать амфетаминами для повышения работоспособности. Это безотносительно окружения
Опять история про окружение и суть встраиваемых языков.
Нет, не только. И выбор Lua неудачен - таргет-группа его не примет - и реализация еще более ухудшает этот выбор.
С Lua на VBA не лучше
лучше и проще. Я с джаваскрипта как-то на VBA переписывал код. Никаких особых проблем не встретил, даже улучшил.
Резюмирую - сначала вы взялись защищать продукт весь и целиком, теперь у вас все-таки плохие бояре хороший продукт испортили, но царь все равно безгрешен.
trinxery
15.09.2022 17:56+2По размерам ничего страшного. если бы вместо Lua взяли питон, например.
мы не берём питон не только потому что он большой, а в том числе и из-за того, что из него многое придётся вырезать, и получится новый ЯП, вместо "везде-одинакого" стандартизированного питона
см. также вашу фразу: "Про питон. Сейчас нет нужды тащить его немаленький весь и целиком. Достаточно обеспечить базовый функционал и дальше подключить кастомные библиотеки "
вот я и задаю вопросы к авторам софта в первую очередь.
(дальше в этой паре абзацев, кстати, претензии опять к софту, а у нас спор про Python/Lua/VBA в разных комбинациях)
все, вываливающееся за пределы куцего набора встроенных функций и операторов, выполняется через C API
стало даже интересно, что такого не могут разработчики софта предоставить через стандартные функции Луа, что нужно аж тащить пробросы в C
лучше и проще. Я с джаваскрипта как-то на VBA переписывал код. Никаких особых проблем не встретил, даже улучшил.
если изначально написано плохо (в разной степени) то можно хоть на C переписывать и будет лучше
сначала вы взялись защищать продукт весь и целиком, теперь у вас все-таки плохие бояре хороший продукт испортили, но царь все равно безгрешен.
Спор начался с вашего утверждения что Луа - "ублюдочен" [по сравнению с VBA]. Ваши аргументы про ужасы написания программ для мойофиса не относятся к Луа, повторюсь, был бы VBA в мойофисе при такой же плохой реализации API самого офиса, было бы так же плохо.
ulitin
16.09.2022 18:09Иван, добрый день, я веду направление исследований и UX, мне и моим коллегам из дизайн команды МойОфис было бы очень интересно поговорить про ваш опыт работы с макросами. Просто напишите мне в телеграм ulitin_kirill и запланируем звонок. Спасибо за неравнодушие!
Areso
15.09.2022 14:41есть куча питоноподобных аналогов. Тащить весь Питон не обязательно.
trinxery
15.09.2022 14:46+6А есть Луа, как раз созданная для применения в данной сфере; создавать новый язык "не обязательно".
IvanSTV
15.09.2022 17:01-2к какой он сфере, кроме садомазохизма применим?
"Lua не имеет встроенных отладочных средств. Взамен, он предлагает специальный интерфейс функций и перехватчиков (hook). Этот интерфейс позволяет строить различные типы отладчиков, профилировщиков и других инструментов, нуждающихся во "внутренней информации" интерпретатора. "
Это предлагается пользователю офисных приложений? Насколько далеки же были они от народа, что понесли это в массы!
trinxery
15.09.2022 17:08+2А это "обычному пользователю" и не нужно. Ему нужно кататься по полям и строить циклы (или что там у вас); Уверен и VBA можно отлаживать с помощью паяльника, а "пользователь" такое вряд ли сможет применить даже чисто технически где-то в каких-то "моих офисах"
IvanSTV
15.09.2022 17:40А это "обычному пользователю" и не нужно. Ему нужно кататься по полям и строить циклы (или что там у вас);
э-э-э... то есть, вы предлагаете вмето банального пошагового исполнения с промптом (как это реализовано в VBA) тестировать цикл через костыли специальных тестов? Как у меня один мужик писал макросы. Посмотрит в интернет, скопирует, ни хрена не понимая. Скопировал - смотрит, что получается на каждом шаге. Ошибка - меняет, параметры. Некорректные данные - меняет. Так и шел методом тыка. А в мойофис предлагается сразу начистовую писать загаженную лишним синтаксисом длинную строку строку и молиться, чтобы исполнилось. Вы сильно далеки от реальных требований пользователя малой автоматизации.
Tresimeno
16.09.2022 13:21Вопрос в том, зачем было тащить туда хоть что, отличное от VBA. В существующих офисных файлах скрипт - это VBA, зачем надо было выделываться и городить свой велосипед? Мотивации так делать я в упор не понимаю.
Areso
16.09.2022 14:37Как бы потому что VBA принадлежит Майкрософту и он не будет счастлив, если кто-то сделает ABV, который будет похож на оригинал до степени смешения.
Akon32
15.09.2022 15:58+2Потому что lua подключить проще (сам подключал, тоже некоторые пользователи плюются).
И вообще, ценность python как встраиваемого языка преувеличена. Он распространён (его знает уйма закончивших курсы людей), много библиотек; и на этом всё. А в остальном lua не хуже как встраиваемый язык.
randomsimplenumber
15.09.2022 13:19+12Экономия 1 строчки кода с одной стороны, ухудшение читабельности с другой стороны. имхо, оно того не стоит.
Rsa97
15.09.2022 13:22+6это функциональность, которая появилась в Python недавно, в версии 3.8
Питону 3.8 уже три года, а актуальная версия 3.10.
omichkun
15.09.2022 13:34+12Вы б хотя бы смотрели Хабр на предмет наличия таких же статей
Habetdin
15.09.2022 15:28+8Причём в обеих статьях ссылки на источник совпадают вплоть до символа. @Boomburum, есть ли в планах детектор таких клонов? :)
NeoCode
15.09.2022 13:59+13Я уже к прошлой статье такой комментарий писал:) Разработчикам языка следовало бы использовать := для ОБЪЯВЛЕНИЯ переменных, а = для присваивания УЖЕ СУЩЕСТВУЮЩИМ переменным (как в Go). Такой подход значительно обезопасил бы код от опечаток в именах переменных (когда вместо присваивания существующей переменной происходит создание новой).
А сейчас получается нечто странное:
x1 = 1 # ok x2 := 2 # error x3 = (y3 := 3) # ok x4 = (y4 = 4) # error
Т.е. один оператор работает только вне скобок, другой только в скобках. Причем возможно и вот такое
c = (d:=1)*(d:=2)
Какой в этом смысл? Не проще ли было просто разрешить обычный оператор = внутри выражений?
igrishaev
15.09.2022 16:12+2для присваивания УЖЕ СУЩЕСТВУЮЩИМ
В питоне нельзя толком проверить, существует переменная или нет. В любой момент ее можно подсунуть через globals.
NeoCode
15.09.2022 20:52Почему? Я заранее предупреждаю что не знаком с Питоном, но в любом интерпретируемом языке переменные обычно хранятся в некоем словаре, где ключ - имя переменной.
Соответственно, нет ничего проще: операция "=" могла бы проверять наличие имени в словаре, и если имени нет - ошибка, если есть - обращение к значению. Операция ":=" аналогично могла бы проверять наличие имени в словаре, но ошибка генерируется если такое имя есть. Если имени нет, то добавлять в словарь имя и значение.
Как именно то или иное имя попало в словарь - совершенно неважно.
onegreyonewhite
16.09.2022 02:44Получилась бы сомнительная польза в ущерб производительности. Словарь в Python'е одна из самых проблемных и медленных сущностей, но на ней держится вся логика переменных. Каждая такая проверка замедлила бы код минимум процентов на 20-30%.
Единственный вариант, как я вижу, если и делать такую проверку, то с помощью mypy. Но кмк это просто никому не нужно, поэтому никто и не делает. Да и, опять же, кмк это только усложнило бы читабельность.
NeoCode
16.09.2022 08:52Словарь это просто ассоциативный массив. Структура данных, основанная на хеш-таблице, дереве того или иного вида или на чем-то еще. Такая проверка уже делается в любом случае при каждом обращении к словарю, естественным путем, она уже существует в коде реализации словаря, потому что словарю нужно в какой-то момент принимать решение - создавать новый элемент или нет. Это решение принимается уже сейчас при каждом обращении к каждой переменной. Т.е. по скорости ничего не изменится.
onegreyonewhite
16.09.2022 13:14Вы предлагаете дважды делать эту проверку или реализовать функционал, при котором в словаре можно будет бросать исключение при наличии ключа?
В любом случае это нафиг никому не нужно, поэтому никто не хочет усложнять код и синтаксис. Единственное, где это могло бы пригодиться - mypy. Но и тут это не нужно никому видимо.
Revertis
15.09.2022 17:40+8Вы можете сказать "Просто добавь
y = func(x)
перед объявлением списка и тебе не понадобится оператор walrus!". Можно так сделать, но для этого потребуется еще одна дополнительная строка кода и, на первый взгляд, без знания о том, чтоfunc(x)
очень медленная, может быть неясно, зачем эта переменная нужна.Решил разрезать на две части:
но для этого потребуется еще одна дополнительная строка кода
А что в этом плохого? У вас буквы платные? Читабельность это главное! Не надо делать так, как в первом примере!
и, на первый взгляд, без знания о том, что
func(x)
очень медленная, может быть неясно, зачем эта переменная нужнаКак зачем??? Чтобы не вызывать 3 раза одну и ту же функцию! Это любой начинающий прогер сам догадается. Вызовы ведь вообще не бесплатные!
NNikolay
15.09.2022 18:42Мне нравятся некоторые примеры. С f-стринг, например. Но первый пункт не очень. Если там такая медленная функция, то проще с этим бороться в самой функции на не в местах её использования. Взять декоратор кеширования из functools, например.
aamonster
А short circuit (короткое замыкание) разве переводят как "короткий цикл"?
EvgeniyZemskiy Автор
Спасибо. Действительно, термин короткое замыкание является устоявшимся, исправил в статье.
RAX7
Это у электриков "короткое замыкание" устоявшийся термин. В данном контексте short circuit всё же переводится как вычисления по короткой схеме
mayorovp
Поскольку термин short circuit является метафорой, прямо отсылающей к "электрикам" — то и перевод можно использовать тот же самый.
А по вышей ссылке наблюдается явная нехватка источников.
trinxery
"short-circuit evaluation" - "вычисление по короткой цепи" (досл.); не похоже что эта метафора так легко используется прямо и без адаптации. Как "КЗ" превратить в эти самые "вычисления" понять крайне затруднительно.
aamonster
Я бы посмотрел перевод в документации M$ и подобных гигантов. У них есть гайдлайны для переводов, так что должно быть всегда одинаково. Там не всегда идеально (от перевода чекбокса я до сих пор подёргиваюсь), но велик шанс, что их перевод будет/станет общепринятым.
mayorovp
Вот документация от Microsoft — последнее место где надо искать правильный перевод. Они даже не пытаются сделать его правильно.
aamonster
Дело не в правильности, а в шансах, что они продавят свой перевод и он станет общепринятым.