len(object)或hasattr(object,__iter__)?

时间:2009-11-19 14:07:30

标签: python

(以下是与python3相关的(如果有的话)。)

这是我编写的代码(简化):

class MyClass:

    def __init__(self):
        self.__some_var = []

    @property
    def some_var(self):
        return self.__some__var

    @some_var.setter
    def some_var(self, new_value):
        if hasattr(new_value, '__iter__'):
            self.__some_var = new_value
        else:
            self.__some_var.append(new_value)

我想在设置时替换它们是否是几个“值”(即,如果new_value是可迭代的,在我的情况下是非可迭代的对象),并且如果它们只是一个“值”则附加。 我很关心hasattr的性能,所以我想知道我是不是应该使用这个setter:

    @some_var.setter
    def some_var(self, *args):
        if len(args) > 1:
            self.__some_var = args
        else:
            self.__some_var.append(args)

感谢您的关注!

3 个答案:

答案 0 :(得分:4)

重要的是hasattr的“性能成本”。它足够快,你很难测量它。

请不要使用__(双下划线)作为您自己的属性。这让我们其他人感到困惑。

通常最好使用collections抽象基类成员资格来处理此类事情。

if isinstance( arg, collections.Sequence ):
    self._some_var = list(arg)
else:
    self._some_var.append( arg )

这为你提供了一些可能更好的工作,因为它更清晰地表达了语义。

答案 1 :(得分:2)

替代方案可能是鸭子打字:

这里我假设您要从迭代中评估(=制作一个列表),因为它可能是一个需要立即扩展以保存的迭代器。

@some_var.setter
def some_var(self, new_value):
    try:
        self.__some_var = list(new_value)
    except TypeError:
        self.__some_var.append(new_value)

如果list()不可迭代,我们希望ValueError提升new_value。作为对你对S.Lott答案的评论的回应,我认为使用hasattr并不是真正的鸭子打字风格。

答案 2 :(得分:0)

在效率方面:

  • hasattr()的最坏情况是O(1)(常数)。
  • append()也是O(1)(常数)的最坏情况。