Форум программистов, компьютерный форум, киберфорум
nekit270
Войти
Регистрация
Восстановить пароль
Карта форума Блоги Сообщество Поиск Заказать работу  
Добро пожаловать, здесь я программирую бессмысленно и беспощадно
Рейтинг: 3.00. Голосов: 4.

"Многостроч­ные" лямбды в Python

Запись от nekit270 размещена 09.12.2023 в 02:36
Метки lambda, python

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

Но эти ограничения можно обойти!

Сразу дам ответ на вопрос "Зачем?" - просто так. Просто захотелось сделать возможным то, что разработчики языка в него не закладывали.

Для начала - ограничение на одну команду. Его легко обойти, используя eval() в связке с генератором списка. Из списка можно взять последний элемент, тогда возвращаемым значением лямбды станет последняя выполненная команда.

Пример:
Python
1
2
x = lambda: [eval(i) for i in ('print("Строка 1")', 'print("Строка 2")', '42 # <- Возвращаемое значение')][-1]
print('Лямбда вернула', x())
Результат:
Код:
Строка 1
Строка 2
Лямбда вернула 42
Теперь - переменные. При попытке присвоить значение переменной внутри eval() будет выброшен SyntaxError, но никто не запрещал использовать getattr() и setattr(), так что можно воспользоваться пустым классом и этими функциями вместо использования переменных.

Пример:
Python
1
2
3
4
5
# Пустой класс для хранения данных внутри eval()
class eval_storage: pass
 
x = lambda: [eval(i) for i in ('setattr(eval_storage,"num",int(input("Введите число: ")))', 'getattr(eval_storage,"num") ** 2')][-1]
print('Число, возведенное в квадрат:', x())
Результат:
Код:
Введите число: 5
Число, возведенное в квадрат: 25
Для атрибутов объектов можно использовать все те же getattr() и setattr(), так что доступ к объектам обеспечен.

P.S. Этот способ был найден мной при создании однострочного приложения на Tkinter, если интересует - могу и про него статью написать.
Размещено в Без категории
Показов 1530 Комментарии 4
Всего комментариев 4
Комментарии
  1. Старый комментарий
    Цитата:
    Сразу дам ответ на вопрос "Зачем?" - просто так. Просто захотелось сделать возможным то, что разработчики языка в него не закладывали....
    если интересует - могу ... статью написать.
    У вас, как мне кажется, очень хорошо получаются тексты в духе "Просто захотелось сделать возможным...". Это всегда интересно читать. Пожалуйста продолжайте.
    Запись от sqltd1 размещена 09.12.2023 в 08:39 sqltd1 вне форума
  2. Старый комментарий
    Аватар для Welemir1
    вы кажется сами придумываете себе сложности и сами с ними боретесь. Про использование евал и создание ненужного списка даже не буду говорить, но вот ваш пример без него, а просто понимая как работает булева логика.
    Python
    1
    2
    3
    4
    5
    
    >>> x = lambda: print("Строка 1") or print("Строка 2") or 42
    >>> print('Лямбда вернула', x())
    Строка 1
    Строка 2
    Лямбда вернула 42
    если прочтете книгу Мерца о функциональных возможностях питона, внезапно сможете в лямбде и цикл написать, и рекурсию использовать
    Запись от Welemir1 размещена 09.12.2023 в 13:35 Welemir1 вне форума
  3. Старый комментарий
    Аватар для Welemir1
    delete
    Запись от Welemir1 размещена 09.12.2023 в 13:35 Welemir1 вне форума
    Обновил(-а) Welemir1 09.12.2023 в 13:36 (повтор)
  4. Старый комментарий
    Аватар для nekit270
    Цитата:
    Сообщение от Welemir1 Просмотреть комментарий
    вы кажется сами придумываете себе сложности и сами с ними боретесь. Про использование евал и создание ненужного списка даже не буду говорить, но вот ваш пример без него, а просто понимая как работает булева логика.
    Насчет создания сложностей самому себе - в точку. я только этим и занимаюсь, это весело
    Возможно, есть и более простые способы, но смысл был как раз придумать еще один, пусть и не самый хороший

    UPD: Ваше решение с or не работает, если команды возвращают что-либо, кроме None, False и им подобных:
    Python
    1
    2
    3
    4
    5
    
    def foo():
        return 92
     
    x = lambda: print('Строка 1') or foo() or print('Строка 2') or 42
    print('Лямбда вернула', x())
    Результат:
    Код:
    Строка 1
    Лямбда вернула 92
    Поэтому ваше решение не универсально.
    Запись от nekit270 размещена 09.12.2023 в 13:52 nekit270 вне форума
 
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2024, CyberForum.ru