Python条件语句(if语句)的最大长度是否有限制?

5

我使用Python的eval()函数生成一个条件语句,代码如下(版本为2.7):

my_list = ['2 > 1','3 > 2','4 > 3']

if eval('(' + ') or ('.join(my_list) + ')'):
    print 'yes'
else:
    print 'no'

在我的情况下,列表是由代码生成的,my_list来自参数文件,并且该列表与'or'语句连接在条件表达式中。上面的代码打印出'yes'。

对于小型列表,它可以正常工作,但在eval()语句中达到一定数量的字符后,我会收到一个字符串错误。

一些搜索发现了这些线程,指向一个错误:

但是他们的max eval()大小比我找到的要大得多。在我的情况下,我发现1744到1803个字符之间出现了问题。我尝试了这段代码,它确实在两个语句之间崩溃了。

>>> eval("1.0*"*10000+"1.0")
1.0
>>> eval("1.0*"*100000+"1.0")
# segfault here

所以,这让我认为问题不在于eval()函数,而是在于if语句中的某个最大值。

有没有另一种有条件地应用列表规则的方法,而不涉及长字符串和eval()函数?

有趣的是,我让my_list变得更大了:

my_list = ['2 > 1']*1000000

而且代码可以正常工作...


如果条件列表是由代码生成的,为什么不立即在生成时对它们进行评估?为什么要进行字符串转换? - Oliver W.
@OliverW。这些条件来自配置文件。由于它们是“或”语句,我不确定如何逐个评估它们。我想我可以设置一个布尔标志,初始值为False,如果其中一个“if”语句评估为True,则将其设置为True。 - philshem
1个回答

9
也许我有所遗漏,但似乎是这样的:
any(map(eval, my_list))

完全符合您的期望。

from itertools import imap

any(imap(eval, my_list)) # Python 2.

这样做的好处是,如果第一个元素的值为真(也称为“短路”),则不会评估列表的其余部分。这可能符合您的需求,也可能不符合。

例如:

> any(map(eval, ['2 > 1','3 > 2','4 > 3']))
True

2
注意:在Python 3中,map只是懒惰的。在2.7中,可以使用itertools.imap来获得相同的效果。 (只是因为OP正在使用Python 2.7而已。) - Carsten
这正好符合我的要求,包括“短路”。对于eval()有很多厌恶,但我没有看到其他方法。 - philshem
1
@philshem:对于eval存在着很多的厌恶,这是有充分理由的。但如果你的目标是“评估一些Python代码”,我认为它是最直接的工具。只需考虑安全性问题以及是否会对你造成问题即可。 - ereOn
@Carsten 在 Python 3 中,'lazy' 是什么意思? - philshem
1
在Python2中,map函数会立即对每个元素执行映射操作。而在Python3中的map和Python2中的imap则会创建一个可迭代对象,在元素被消耗时才会对其进行映射操作。因此,在非惰性情况下,所有元素都会被计算,而在惰性情况下,只有第一个计算结果为真的元素及其之前的元素会被计算。 - KillianDS

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接