Define a lambda expression that raises an Exception
Hire the world's top talent on demand or became one of them at Toptal: https://topt.al/25cXVn
and get $2,000 discount on your first invoice
--------------------------------------------------
Music by Eric Matyas
https://www.soundimage.org
Track title: Horror Game Menu Looping
--
Chapters
00:00 Define A Lambda Expression That Raises An Exception
00:17 Accepted Answer Score 271
01:17 Answer 2 Score 96
01:28 Answer 3 Score 19
03:35 Answer 4 Score 18
03:59 Thank you
--
Full question
https://stackoverflow.com/questions/8294...
--
Content licensed under CC BY-SA
https://meta.stackexchange.com/help/lice...
--
Tags
#python
#avk47
ACCEPTED ANSWER
Score 271
There is more than one way to skin a Python:
y = lambda: (_ for _ in ()).throw(Exception('foobar'))
Lambdas accept statements. Since raise ex is a statement, you could write a general purpose raiser:
def raise_(ex):
    raise ex
y = lambda: raise_(Exception('foobar'))
But if your goal is to avoid a def, this obviously doesn't cut it. It does, however allow you to conditionally raise exceptions, e.g.:
y = lambda x: 2*x if x < 10 else raise_(Exception('foobar'))
Alternatively you can raise an exception without defining a named function. All you need is a strong stomach (and 2.x for the given code):
type(lambda:0)(type((lambda:0).func_code)(
  1,1,1,67,'|\0\0\202\1\0',(),(),('x',),'','',1,''),{}
)(Exception())
And a python3 strong stomach solution:
type(lambda: 0)(type((lambda: 0).__code__)(
    1,0,1,1,67,b'|\0\202\1\0',(),(),('x',),'','',1,b''),{}
)(Exception())
Thanks @WarrenSpencer for pointing out a very simple answer if you don't care which exception is raised: y = lambda: 1/0.
ANSWER 2
Score 96
How about using exec, a built-in function in Python 3?
lambda x: exec('raise(Exception(x))')
ANSWER 3
Score 19
Actually, there is a way, but it's very contrived.
You can create a code object using the compile() built-in function.  This allows you to use the raise statement (or any other statement, for that matter), but it raises another challenge: executing the code object.  The usual way would be to use the exec statement, but that leads you back to the original problem, namely that you can't execute statements in a lambda (or an eval(), for that matter).
The solution is a hack.  Callables like the result of a lambda statement all have an attribute __code__, which can actually be replaced.  So, if you create a callable and replace it's __code__ value with the code object from above, you get something that can be evaluated without using statements.  Achieving all this, though, results in very obscure code:
map(lambda x, y, z: x.__setattr__(y, z) or x, [lambda: 0], ["__code__"], [compile("raise Exception", "", "single"])[0]()
The above does the following:
the
compile()call creates a code object that raises the exception;the
lambda: 0returns a callable that does nothing but return the value 0 -- this is used to execute the above code object later;the
lambda x, y, zcreates a function that calls the__setattr__method of the first argument with the remaining arguments, AND RETURNS THE FIRST ARGUMENT! This is necessary, because__setattr__itself returnsNone;the
map()call takes the result oflambda: 0, and using thelambda x, y, zreplaces it's__code__object with the result of thecompile()call. The result of this map operation is a list with one entry, the one returned bylambda x, y, z, which is why we need thislambda: if we would use__setattr__right away, we would lose the reference to thelambda: 0object!finally, the first (and only) element of the list returned by the
map()call is executed, resulting in the code object being called, ultimately raising the desired exception.
It works (tested in Python 2.6), but it's definitely not pretty.
One last note: if you have access to the types module (which would require to use the import statement before your eval), then you can shorten this code down a bit: using types.FunctionType() you can create a function that will execute the given code object, so you won't need the hack of creating a dummy function with lambda: 0 and replacing the value of its __code__ attribute.
ANSWER 4
Score 18
If all you want is a lambda expression that raises an arbitrary exception, you can accomplish this with an illegal expression. For instance, lambda x: [][0] will attempt to access the first element in an empty list, which will raise an IndexError.
PLEASE NOTE: This is a hack, not a feature. Do not use this in any (non code-golf) code that another human being might see or use.