Python如何处理列表推导中的多个条件?

时间:2015-11-12 17:08:36

标签: python list

我试图从我拥有的函数创建列表理解,并且遇到了意外的行为。为了更好地理解,我的函数得到一个整数并检查它的哪个数字完全除以整数:

# Full function
divs = list()
for i in str(number):
    digit = int(i)
    if digit > 0 and number % digit == 0:
        divs.append(digit)
return len(divs)

# List comprehension
return len([x for x in str(number) if x > 0 and number % int(x) == 0])

问题在于,如果我将1012作为输入,则完整函数返回3,这是预期的结果。列表推导返回ZeroDivisionError: integer division or modulo by zero。我明白这是因为这个条件:

if x > 0 and number % int(x) == 0

在完整功能中,多个条件从左到右处理,所以很好。在列表理解中,我真的不知道,但我猜测它没有以同样的方式处理。

直到我尝试使用更简单的功能:

# Full function
positives = list()
for i in numbers:
    if i > 0 and 20 % i ==0:
        positives.append(i)
return positives

# List comprehension
return [i for i in numbers if i > 0 and 20 % i == 0]

他们都工作了。所以我想也许它与number % int(x)有关?这只是对它如何真正起作用的好奇心?有什么想法吗?

2 个答案:

答案 0 :(得分:6)

列表理解是不同的,因为您比较x > 0而不将x转换为int。在Py2中,不匹配的类型将在arbitrary and stupid but consistent way中进行比较,在这种情况下,所有str s(x的类型)都大于所有int(类型0)意味着x > 0测试始终为True,第二个测试始终执行(有关此无意义的详细信息,请参阅下面的脚注)。将列表理解更改为:

[x for x in str(number) if int(x) > 0 and number % int(x) == 0]

它会起作用。

请注意,您可以通过在代码顶部导入Py3版mapfrom future_builtins import map)并使用生成器表达式来进一步简化(并限制冗余工作和内存消耗)使用sum,而不是len的列表理解:

return sum(1 for i in map(int, str(number)) if i > 0 and number % i == 0)

每个数字只调用int一次,并且不构造中间list

脚注0是一种数字类型,所有数字类型都比None以外的所有数字类型都小,因此str总是大于0 dict。在非数字情况下,它将比较字符串类型名称,因此frozenset&lt; list&lt; set&lt; str&lt; tuple&lt; frozenset,除了哎呀,setfrozenset() < []相互比较“自然”,因此您可以拥有非传递关系; [] < set()为真,frozenset() < set()为真,但with given (seq, location) as ( values (1,'LA'), (2,'LB'), (3,'LC') ), route_details (route, seq, location) as ( values ('RA',1,'LA'), ('RA',2,'LB'), ('RA',3,'LC'), ('RC',1,'LA'), ('RC',2,'LB'), ('RC',3,'LC'), ('RC',4,'LD'), ('RB',1,'LB'), ('RB',3,'LC'), ('RB',2,'LA') ) select route from route_details left join given using (seq, location) group by route having (select count(*) from given) = count(*) ; route ------- RA RB 为假,因为特定类型的比较器在最终版本中被调用。就像我说的那样,任意而混乱;它是从Python 3中删除的原因。

答案 1 :(得分:0)

你应该说int(x)&gt;列表理解中的0