Обновить
52
0.1
Valentin Nechayev@netch80

Программист (backend/сети)

Отправить сообщение

Я начинал ещё на терминалах ЕС7066, там клавиатура была толстенная и с заметным подъёмом от пользователя. Видимо, кто-то так раньше рассчитывал. Поэтому привык поднимать задние подставки на PCшных клавах.
Только прочитав про туннельный синдром перестал поднимать эти подставки (хоть мне, скорее всего, этот синдром и не грозит).

Кажется, это осталось у них только во ThinkPad линии? У остальных линий такого нет.

Справедливости ради я бы заметил, что часть описанного вами это полезная вариативность. Кому-то нужен полноценный нумпад, а кому-то он, наоборот, мешает, или лаптоп маленький, или клавиатура нужна только 60%... Зато цифровой режим нумпада, мне кажется, очень хорошая идея именно если требуется "бухгалтерский" режим.

А вот форма Enter (ВК) это следствие различия стандартов ANSI и ISO, и метания правой "|" вокруг неё - по той же причине. Клавиша в позиции B00 (между LShift и Z в нашем варианте) с обозначениями (для России, Украины и т.д.) "|" это настолько неудобно, что авторов ISO9995 хочется слегка пожечь синим пламенем и заставить их официально перенести её в позицию B11 (откусив кусок от RShift и тем самым сделав шифты примерно равными по ширине).

Курсор... вот новый игровой Asus меня таки бесит. PgUp, PgDn, Home, End только как Fn+↑↓←→ соответственно, а там, где их привычно искать - мультимедийный набор. Не знаю, сколько ещё привыкать.

Сейчас на Win11 24H2 мне эта комбинация четырёх модификаторов без целевой клавиши вызвала окно "Welcome to Microsoft 365 Copilot" (после чего начало делать вид, что работает).
Видимо, эффект от неё меняется в зависимости от последнего постановления ВЦСПС службы продажников?
Мне не нравится, что это только модификаторы без единой целевой клавиши. Но после сочетаний Ctrl+Shift и Alt+Shift удивляться не приходится.

Всегда назначаю CapsLock на эту функцию. Индикатор - ScrollLock, если есть на клавиатуре, ну и в трее DM.

Дайте, пожалуйста, точную ссылку на фото той модели, которую имеете в виду. А то их много, и ни одна, что нашлась поиском, не отвечает моему запросу.

Так вы попробуйте не просто нажимать, а нажать, спросить, поработать в другом окне, опять нажать.

Да, почему-то после этого он открылся только со второго нажатия. Но открылся, и после этого снова - закрывается и открывается по кругу.
Какой-то эффект там есть, но совсем критичного нет.

Printscreen для вас какая-то шутка?

Это не та же PrintScreen, что традиционно известна со времён клавиатуры XT (отдельной кнопкой - AT-101), та тоже есть (на нём как Fn+Q). Это отдельная кнопка, которая именно что посылает последовательность Shift+Win+S, в виде соответствующих сканкодов нажатия и отжатия. Вы это, очевидно, пропустили в моём сообщении, как и то, что эта комбинация делает не то же, что и классический PrintScreen.

Про "шутку" я не говорил, не надо приписывать мне не мои слова. А вот что это эксперимент, который могут не продолжить - да, именно так.

Прошу таки быть внимательнее к деталям.

11ка 24H2 26100.4946: нажал - всплыло окно Copilot поверх всех, нажал снова - исчезло, и так по кругу.

Я, как юниксоед всю свою карьеру, приветствовал этот шаг по направлению к Space-Cadet keyboard, даже ещё когда не знал про неё:) Super есть. Ещё три модификатора бы, только размещение придумать.

Вы не понимаете:)
На клавиатуре Sven 301 есть кнопка вызова калькулятора. На моём Acer Aspire годовой давности кнопка для съёма скриншота, что соответствует комбинации Win+Shift+S. На свежекупленном игровом Asus есть отдельная кнопка для MS Copilot.
Всё это эксперименты, которые могут жить недолго, а могут закрепиться. Клавиша Win закрепилась потому, что стала ещё одним модификатором там, где программы успели позанимать все возможные комбинации из Ctrl и Alt, и заводить новые стало невозможно из-за конфликтов с программами (названные вами Ctrl+Esc, Shift+F10 уже тоже местами позанимали), а этот Win гарантированно закреплён за системным уровнем. Ну а в Unix мире сказали спасибо "о, дали Super! Жаль, что пока без Hyper, Top и Front, но уже отлично!"

На лаптопах обычно не ставят динамик для этого, а вот у десктопных материнок есть контакты, а если не сильно дешёвая, то и крошечный динамик в комплекте, кто хочет, тот прицепляет его.

Вот даже внутри кода, а не снаружи от тела текущей функции и без Type Annotations?

Ну где написать def make_adder из моего примера - вопрос стиля и чуть производительности, может, тут будет оптимизация, если увидят, что сама эта функция "чистая" и окружение не захватывает. Можно и снаружи. Так и класс описывать можно и внутри, и снаружи. Если снаружи - к нему надо идти, его читать, ещё и в логике отдельно инициализатор, а отдельно __call__, а если def, то всё это более связно.

Вдобавок, я просто очень не люблю вложенные функции и использование там "внешних" переменных.

Вот это точно вкусовщина. Я понимаю, но именно вариант описать где используется и предельно прямо в коде - по мне (и по команде), выигрывает в среднем. Дао Питона, как известно, "явное лучше неявного", даже когда от этого страдает производительность.

а вот в случае с lambda, по крайней мере, PyCharm туда не залезает.

Это явная недоработка PyCharm, но да, может быть проблемой. У меня самые толстые проекты, где реально нужно что-то отлаживать, это телефония, там интерактивным отладчиком не залезешь - надо только логать. Поэтому мне такая разница не очень важна. Имя функции в стектрейсе, да, регулярно важно.

И поменять я ее могу w._x = 2*w._x, Ваш ход?

func.__closure__. Неизменяемо, да (ну если без особых хаков), но и не было нужно. Опять таки специфика, вот ещё ни разу за 20+ лет с питоном не делал такое;
Заранее признаю, что мой домен сильно перекошен.

Но вот читабельность мы сравнивали - и явный def в среднем лучше всего, а вот делать класс с __call__ заметно проигрывало, по общему мнению команды.

Ну, совсем не проблема. Единственно что - порядок аргументов в случае лямбды неудобный (может, я ещё какого трюка не знаю), но в случае функции уже проблем нет:

adders = []
for x in (111, 222, 333, 444, 555, 666):
    ## Вот тут если писать lambda x=x, y - ругается: 
    ## SyntaxError: non-default argument follows default argument
    adders.append(lambda y, x=x: x+2*y)
for y in [-1, 0, 1]:
    print([w(y) for w in adders])
print('-'*64)
adders = []
def make_adder(x):
    def adder(y):
        return x + 2*y
    return adder
for x in (111, 222, 333, 444, 555, 666):
    adders.append(make_adder(x))
for y in [-1, 0, 1]:
    print([w(y) for w in adders])

Можно было бы ещё с functools.partial построить, но не хочется влезать. Вариант с def внутри функции-создателя (которая таким образом создаёт блок) более чем достаточен.

Вероятно, ваш вариант выгоднее по времени, тут уже надо бенчмаркать, и не на голом коде, а в чём-то более-менее реальном. Но мне сейчас неоткуда взять такое реальное. И для большинства читателей, я думаю, вложенная функция понятнее.

Можете привести пример именно в вашем стиле? (Хочу избежать ещё 1-2 циклов доводки/шлифовки.)

Это если вы встроенный float округляете:) А вот эффект следующего уровня:

>>> from decimal import *
>>> getcontext().rounding = ROUND_DOWN
>>> round(Decimal("1.5"), 0)
Decimal('1')
>>> round(Decimal("2.5"), 0)
Decimal('2')
>>> getcontext().rounding = ROUND_UP
>>> round(Decimal("1.5"), 0)
Decimal('2')
>>> round(Decimal("2.5"), 0)
Decimal('3')
>>> getcontext().rounding = ROUND_05UP
>>> round(Decimal("3.5"), 0)
Decimal('3')
>>> round(Decimal("4.5"), 0)
Decimal('4')
>>> round(Decimal("5.5"), 0)
Decimal('6')
>>> round(Decimal("6.5"), 0)
Decimal('6')

Функция стандартная round(), но зависит от контекста, определённого где-то там далеко, потому что реально у объекта она вызывает __round__(), а он уже знает, куда смотреть. А ещё round(x) и round(x, 0) тут работают по-разному.

В моём практическом случае нужна была именно функция, потому что какая функция вызывается - тоже было важно.

Ну, у меня была задача сравнить собственно функцию с функцией, в зависимости от метода создания. Довернуть ещё и объект с возможностью вызова как функция это уже следующий уровень наворота, полезный где-то на практике, но тут затрудняющий понимание примера.

Разумеется, он также показывает, как создание нового контекста (а тут это объект) помогает отвязаться от одного контекста на всех.

Вот тестик (давно валялся, вытащил к теме):

def moo(x):
    return repr(x)

def gen_moof2(i):
    def moof2():
        return moo(i)
    return moof2

if __name__ == "__main__":
    clos_l1 = []
    clos_l2 = []
    clos_f1 = []
    clos_f2 = []
    for i in range(4):
        p_i = str(i)
        clos_l1.append(lambda: moo(p_i))
        clos_l2.append(lambda p_i=p_i: moo(p_i))
        def moof1():
            return moo(p_i)
        clos_f1.append(moof1)
        clos_f2.append(gen_moof2(p_i))
    print(*[x() for x in clos_l1])
    print(*[x() for x in clos_l2])
    print(*[x() for x in clos_f1])
    print(*[x() for x in clos_f2])

Выводит, Python 3.10.12:

'3' '3' '3' '3'
'0' '1' '2' '3'
'3' '3' '3' '3'
'0' '1' '2' '3'

То есть от того, что мы просто завернули в функцию (локальный def) вместо лямбды, ничего не поменялось: копия значения для конкретного замыкания - не создалась.

Чтобы её создать, надо явно скопировать переменную. А чтобы эта копия была действительно уникальной - нужно своё пространство, что достигается, как сказано в статье, или аргументами лямбды, или отдельной функцией - генератором этой самой лямбды.

А то, что у def есть имя, а у lambda - нет, вопрос не связанный. Кстати, тут переопределение имени функции может быть нужно даже при def, если нам нужен какой-то уникальный идентификатор для трейса.

Информация

В рейтинге
4 199-й
Откуда
Киев, Киевская обл., Украина
Дата рождения
Зарегистрирован
Активность