Определить выражение лямбда, которое вызывает исключение

Как я могу написать выражение лямбда, которое эквивалентно:

def x(): raise Exception() 

Не допускается следующее:

 y = lambda : raise Exception() 

5 Solutions collect form web for “Определить выражение лямбда, которое вызывает исключение”

ОБНОВЛЕНИЕ 2: Я был неправ! Оказывается, есть более чем один способ скрыть Python:

 y = lambda: (_ for _ in ()).throw(Exception('foobar')) 

Нет. Лямбдас только принимает выражения. raise ex – это утверждение. Конечно, вы могли бы написать рейдер общего назначения:

 def raise_(ex): raise ex y = lambda: raise_(Exception('foobar')) 

Но если ваша цель – избежать def , это, очевидно, не сократит его. Это, однако, позволяет условно вырабатывать исключения, например:

 y = lambda x: 2*x if x < 10 else raise_(Exception('foobar')) 

UPDATE: ОК, поэтому вы можете создать исключение без определения именованной функции. Все, что вам нужно, это сильный желудок (и 2.x для данного кода):

 type(lambda:0)(type((lambda:0).func_code)( 1,1,1,67,'|\0\0\202\1\0',(),(),('x',),'','',1,''),{} )(Exception()) 

ОБНОВЛЕНИЕ 3: И сильное желудочное решение python3:

 type(lambda: 0)(type((lambda: 0).__code__)( 1,0,1,1,67,b'|\0\202\1\0',(),(),('x',),'','',1,b''),{} )(Exception()) 

Как насчет:

 lambda x: exec('raise(Exception(x))') 

На самом деле, есть способ, но это очень надуманно.

Вы можете создать объект кода с помощью встроенной функции compile() . Это позволяет использовать оператор raise (или любой другой оператор, если на то пошло), но это вызывает еще одну проблему: выполнение объекта кода. Обычным способом было бы использовать оператор exec , но это вернет вас к исходной проблеме, а именно, что вы не можете выполнять инструкции в lambda (или eval() , если на то пошло).

Решение – это взлом. Вызываемые вызовы, такие как результат применения lambda имеют атрибут __code__ , который может быть фактически заменен. Итак, если вы создаете вызываемый и заменяете его значением __code__ с помощью объекта кода сверху, вы получаете то, что может быть оценено без использования операторов. Однако достижение всего этого приводит к очень неясному коду:

map(lambda x, y, z: x.__setattr__(y, z) or x, [lambda: 0], ["__code__"], [compile("raise Exception", "", "single"])[0]()

Вышеизложенное делает следующее:

  • вызов compile() создает объект кода, который вызывает исключение;

  • lambda: 0 возвращает вызываемый, который ничего не делает, но возвращает значение 0 – это используется для выполнения вышеуказанного объекта кода позже;

  • lambda x, y, z создает функцию, которая вызывает метод __setattr__ первого аргумента с остальными аргументами, и ВОЗВРАЩАЕТ ПЕРВОЕ АРГУМЕНТ! Это необходимо, потому __setattr__ сам __setattr__ возвращает None ;

  • вызов map() принимает результат lambda: 0 , а с помощью lambda x, y, z заменяет его __code__ объектом результатом вызова compile() . Результатом этой операции карты является список с одной записью, возвращаемый lambda x, y, z , поэтому нам нужна эта lambda : если бы мы немедленно использовали __setattr__ , мы потеряли бы ссылку на lambda: 0 объект!

  • наконец, выполняется первый (и только) элемент списка, возвращаемый вызовом map() , в результате чего вызываемый объект кода, в конечном счете, создает желаемое исключение.

Он работает (протестирован в Python 2.6), но это определенно не очень.

Последнее замечание: если у вас есть доступ к модулю types (который должен использовать оператор import до вашего eval ), вы можете немного сократить этот код: используя types.FunctionType() вы можете создать функцию, которая будет выполняться данный объект кода, поэтому вам не понадобится взлом создания фиктивной функции с lambda: 0 и замена значения его атрибута __code__ .

Если все, что вы хотите, является выражением лямбда, которое вызывает произвольное исключение, вы можете выполнить это с помощью незаконного выражения. Например, lambda x: [][0] попытается получить доступ к первому элементу в пустом списке, что вызовет индекс IndexError.

ПОЖАЛУЙСТА, ОБРАТИТЕ ВНИМАНИЕ : Это взлом, а не функция. Не используйте этот код (без кода-гольфа), который может видеть или использовать другой человек.

Функции, созданные с помощью лямбда-форм, не могут содержать операторов .

  • Подсчет слов, начинающихся с символа
  • Соединения / очереди с несколькими резьбовыми соединениями
  • Перекрестное произведение двух векторов в Python
  • найти разницу во времени в секундах как целое число с питоном
  • Что делает classmethod в этом коде?
  • удаление элементов из списка
  • Лучший способ удалить элемент из файла dict
  • Должен ли я использовать «из пакетов импорта, настроек» или «из. import utils, настройки "
  • Python - лучший язык программирования в мире.