我在How to Think Like a Computer Scientist(here)中遇到了以下内容:
def recursive_sum(nested_num_list):
sum = 0
for element in nested_num_list:
if type(element) == type([]):
sum = sum + recursive_sum(element)
else:
sum = sum + element
return sum
我对使用type(element)== type([])感到震惊。这不仅是不好的做法,而且这个功能不适用于任何其他序列类型。多态性是避免类型比较的典型方法,但不能在此处使用。在这种情况下如何避免类型比较?我考虑过:
def recursive_sum(nested_sum_list):
sum = 0
for element in nested_num_list:
try:
sum += element
except TypeError:
sum += recursive_sum(element)
return sum
这使得该功能适用于其他序列,但仍然有点粗略。谢谢!
答案 0 :(得分:3)
您可以使用isinstance(element, collections.Sequence)
检查元素是否为序列。
答案 1 :(得分:2)
“sum”函数采用迭代,所以我会检查元素是否实现了__iter__
方法,使用“hasattr”内置函数。
像这样:
def recursive_sum(nested_num_list):
sum = 0
for element in nested_num_list:
if hasattr(element, '__iter__'):
sum = sum + recursive_sum(element)
else:
sum = sum + element
return sum
答案 2 :(得分:1)
对于aribtrarily嵌套列表的展平,您将始终需要某种检查来测试元素本身是可迭代还是叶节点。我不会将flattening与在一个函数中计算总和相结合,而是定义一个只进行展平的生成器函数:
def flatten(x):
try:
it = iter(x)
except TypeError:
yield x
else:
for i in it:
for j in flatten(i):
yield j
这样,您将在单个函数中包含所有丑陋的位。对于嵌套序列x
,您现在可以执行
sum(flatten(x))
获得递归总和。
答案 3 :(得分:1)
列表中的事情:
>>> import collections
>>> hasattr(element, '__getitem__')
True
>>> not hasattr(element, 'keys')
True
>>> isinstance(element, collections.Sequence)
True
>>> hasattr(element, '__iter__')
True
字符串的真实情况:
>>> string = '1234'
>>> hasattr(string, '__getitem__')
True
>>> not hasattr(string, 'keys')
True
>>> isinstance(string, collections.Sequence)
True
>>> hasattr(string, '__iter__')
False
答案 4 :(得分:0)
你在这里看到的不是我所知道的任何语言的多态性。 +=
列表意味着一件事,对于数字而言另一件事。你希望+=
列表表示不寻常的东西(总结所有元素并返回总和) - 但这只对你的具体例子有意义。对于其他(大多数,我会说)列表的使用,+=
的原始含义更方便。
为了使这种行为真正具有多态性,您可以从list
派生并使+=
表示您想要的 - 然后您就不需要这些黑客了。
顺便说一句:
if type(element) == type([]):
应改写为:
if isinstance(element, list):
答案 5 :(得分:0)
您正在检查是否可以将元素添加到int中,这不是您想要的。
虽然try
并不坏:尝试将其用作可迭代的 - 如果它有效,则它是可迭代的:
def recursive_sum(nested_sum_list):
sum = 0
# this raises TypeError if element is not a sequence
for element in nested_num_list:
try:
sum += recursive_sum(element)
except TypeError:
sum += element
return sum
迭代物也有typeclass:
import collections
print isinstance(element, collections.Iterable)
基本上只搜索__iter__
方法。
答案 6 :(得分:0)
此函数的目的不是普遍适用于添加嵌套结构,它只是为了说明递归而创建的。
添加更复杂的序列类型检查,尝试和除外,或者添加除数字之外的其他东西的能力会使函数 less 作为递归的学习工具。
话虽如此,isinstance(element, (list, tuple))
在这里可能更合适,并且不会增加任何复杂性。