定义引发exception的lambdaexpression式

我怎样才能写一个等同于下面的lambdaexpression式?

def x(): raise Exception() 

以下是不允许的:

 y = lambda : raise Exception() 

更新2:我错了! 事实certificate,有不止一种方式来皮肤的Python:

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

不,兰姆达斯只接受expression。 raise ex是一个声明。 当然,你可以写一个通用的提升者:

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

但如果你的目标是避免def ,这显然不会削减它。 不过,它可以让你有条件地提出exception,例如:

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

更新:好的,所以你可以引发一个exception,而不需要定义一个命名函数。 所有你需要的是一个强大的胃(和2.x给定的代码):

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

更新3:和python3 强大的胃解决scheme:

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

更新4:谢谢@WarrenSpencer指出一个非常简单的答案,如果你不在乎引发了哪个exception: y = lambda: 1/0

怎么样:

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

实际上,有一个办法,但是很有人气。

您可以使用compile()内置函数创build一个代码对象。 这允许你使用raise语句(或者任何其他语句),但是它提出了另一个挑战:执行代码对象。 通常的方法是使用exec语句,但这导致你回到原来的问题,即你不能在一个lambda (或eval() ,执行语句)。

解决scheme是一个黑客。 象lambda语句的结果__code__ ,可加__code__都有一个属性__code__ ,它可以被replace。 所以,如果你创build了一个可调用的对象,并用上面的代码对象replace它的__code__值,那么你可以得到一些不需要使用语句就可以评估的东西。 实现这一切,但是,导致非常模糊的代码:

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

以上做了以下工作:

  • compile()调用会创build一个引发exception的代码对象;

  • lambda: 0返回一个可调用的函数,它什么也不做,只是返回值0 – 这个被用来稍后执行上面的代码对象;

  • lambda x, y, z创build一个函数,用其余参数调用第一个参数的__setattr__方法,并返回第一个参数! 这是必要的,因为__setattr__本身返回None ;

  • map()调用的结果是lambda: 0 ,并且使用lambda x, y, z__code__ compile()调用的结果replace为__code__对象。 这个映射操作的结果是一个列表,只有一个条目,由lambda x, y, z ,这就是为什么我们需要这个lambda :如果我们马上使用__setattr__ ,我们将失去对lambda: 0的引用lambda: 0目的!

  • 最后,执行map()调用返回的列表的第一个(也是唯一的)元素,导致调用代码对象,最终引发所需的exception。

它工作(在Python 2.6中testing),但它绝对不漂亮。

最后一个注意:如果你有权访问types模块(在你的eval之前需要使用import语句),那么你可以缩短这个代码:using types.FunctionType()你可以创build一个函数来执行给定的代码对象,所以你不需要用lambda: 0创build一个虚拟函数,并replace它的__code__属性的值。

如果你想要的只是一个引发任意exception的lambdaexpression式,你可以用一个非法的expression来完成。 例如, lambda x: [][0]将尝试访问空列表中的第一个元素,这将引发IndexError。

请注意 :这是一个黑客,而不是一个function。 不要使用这是另一个人可能会看到或使用的任何(非代码高尔夫)代码。

用lambda表单创build的函数不能包含语句 。