Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/sqlite/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 避免在多态性获胜的情况下使用type()比较';行不通_Python_Types - Fatal编程技术网

Python 避免在多态性获胜的情况下使用type()比较';行不通

Python 避免在多态性获胜的情况下使用type()比较';行不通,python,types,Python,Types,我在()中遇到了以下情况: 我对type(element)==type([])的使用感到震惊。这不仅是一种糟糕的做法,而且这个函数对任何其他序列类型都不起作用。多态性是避免类型比较的典型方法,但不能在这里使用。在这种情况下,如何避免类型比较?我认为: def recursive_sum(nested_sum_list): sum = 0 for element in nested_num_list: try: sum += element

我在()中遇到了以下情况:

我对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

这使得该函数适用于其他序列,但仍然有点粗糙。谢谢

对于任意嵌套列表的展平,您总是需要某种检查来测试元素本身是iterable还是leaf节点。我不会将展平与计算一个函数中的和结合起来,而是定义一个只进行展平的生成器函数:

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))

获取递归和。

在我所知的任何语言中,您在这里看到的都不是多态性<代码>+=对于列表意味着一件事,对于数字意味着另一件事。您希望列表具有不同寻常的含义(汇总所有元素并返回总和),但这仅对您的特定示例有意义。对于列表的其他(我想说是大多数)用法,
+=
的原始含义要方便得多

要使其真正具有多态性,您可以从
列表中派生出
+=
,并使
+=
表示您想要的意思-这样您就不需要这些黑客

顺便说一句:

应改写为:

if isinstance(element, list):

您正在检查元素是否可以添加到int,这不是您想要的

不过,
try
还不错:试着把它当作一个iterable使用——如果它起作用,那么它就是一个iterable:

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
对于iterables,还有一个解决方案:

import collections
print isinstance(element, collections.Iterable)
它基本上只是搜索一个
\uuuuuuuuuuuuuuuuuu
方法。

“sum”函数接受一个iterable,所以我会使用“hasattr”内置函数检查元素是否实现了
\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu

像这样:

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

您可以使用isinstance(element,collections.sequence)检查元素是否是序列

此函数的目的不是为了普遍适用于添加嵌套结构,它只是为了演示递归而创建的

添加更复杂的序列类型检查、try和except,或者添加数字以外的内容,都会降低该函数作为递归学习工具的实用性


也就是说,
isinstance(element,(list,tuple))
在这里可能更合适,并且不会增加任何复杂性。

列表的真实情况:

>>> 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

很好,但效率极低-大多数子元素可能是数字,而不是列表,因此会抛出大量异常。这实际上是我想到的第一件事,但后来我意识到,“检查元素是否可以添加到int”在绝大多数情况下在功能上是等效的,计算上是优越的,而且(可以说)语义上更准确。它确实反转了原始函数的逻辑,但这很好。不管怎样,谢谢你提出这个备选方案。@Bryan Head:是的,这个函数可能更有意义,但你问了一个不同的问题:如何识别iterables,我试着回答这个问题:-)注意,有些iterables没有
\uuuUr\uUr
属性。要测试对象是否可编辑,请使用
try:iter(x);除了TypeError:…
isinstance(x,collections.Iterable)
。iter(x)将为string返回True,如果您的实际用途列表喜欢集合展平,您希望避免这种情况
isinstance(x,collections.Sequence)
是一个更好的方法choice@Imram:在递归求和的情况下,嵌套序列中的任何位置都不应出现字符串,但最好有一个包含生成器的列表,如
[重复(3,10),重复(1,5)]
。这就是为什么我更愿意在这里测试
Iterable
。Sven-任何Iterable示例都没有
\uuuuuuuuuuuuuuuu
?如果需要的话,我可以为这个问题单独发帖。@布赖恩:这之前已经讨论过了。不幸的是,我现在记得的唯一一个例子是字符串,不知何故,我在这篇文章中的第一条评论就没有了意义……在静态类型语言中,您可以使用具有不同类型签名的函数重载函数。字符串是序列。如果你不想这样对待他们,你必须为他们破例。
>>> 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