我试图从我拥有的函数创建列表理解,并且遇到了意外的行为。为了更好地理解,我的函数得到一个整数并检查它的哪个数字完全除以整数:
# 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)
有关?这只是对它如何真正起作用的好奇心?有什么想法吗?
答案 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版map
(from 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
< list
< set
< str
< tuple
< frozenset
,除了哎呀,set
和frozenset() < []
相互比较“自然”,因此您可以拥有非传递关系; [] < 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