【问题标题】:如何获取列表中的元素数量?
【发布时间】:2010-12-15 07:06:06
【问题描述】:

考虑以下几点:

items = []
items.append("apple")
items.append("orange")
items.append("banana")

# FAKE METHOD:
items.amount()  # Should return 3

如何获取列表items的元素个数?

【问题讨论】:

标签: python list


【解决方案1】:

len() 函数可用于 Python 中的多种不同类型 - 内置类型和库类型。例如:

>>> len([1, 2, 3])
3

【讨论】:

    【解决方案2】:

    如何获取列表的大小?

    要查找列表的大小,请使用内置函数len

    items = []
    items.append("apple")
    items.append("orange")
    items.append("banana")
    

    现在:

    len(items)
    

    返回 3。

    说明

    Python 中的一切都是对象,包括列表。所有对象在 C 实现中都有某种标题。

    Python 中具有“大小”的列表和其他类似的内置对象,特别是有一个名为ob_size 的属性,其中缓存了对象中的元素数量。因此检查列表中的对象数量非常快。

    但是,如果您要检查列表大小是否为零,请不要使用 len - 而应使用 put the list in a boolean context - it treated as False if empty, True otherwise

    来自docs

    len(s)

    返回对象的长度(项目数)。参数可以是一个序列(例如字符串、字节、元组、列表或范围)或 集合(例如字典、集合或冻结集合)。

    len 是用__len__ 实现的,来自数据模型docs

    object.__len__(self)

    调用以实现内置函数len()。应该返回对象的长度,一个整数 >= 0。另外,一个不 定义一个 __nonzero__() [在 Python 2 中或在 Python 3 中的 __bool__()] 方法并且其 __len__() 方法返回零 在布尔上下文中被认为是错误的。

    我们还可以看到__len__是一个列表方法:

    items.__len__()
    

    返回 3。

    你可以得到len(长度)的内置类型

    事实上,我们看到我们可以获得所有描述类型的信息:

    >>> all(hasattr(cls, '__len__') for cls in (str, bytes, tuple, list, 
                                                range, dict, set, frozenset))
    True
    

    不要使用len 来测试空或非空列表

    要测试特定长度,当然,只需测试相等性:

    if len(items) == required_length:
        ...
    

    但是有一种特殊情况可以测试零长度列表或相反的列表。在这种情况下,不要测试相等性。

    另外,不要这样做:

    if len(items): 
        ...
    

    相反,只需这样做:

    if items:     # Then we have some items, not empty!
        ...
    

    if not items: # Then we have an empty list!
        ...
    

    explain why here 但简而言之,if itemsif not items 更具可读性和性能。

    【讨论】:

      【解决方案3】:

      虽然这可能没有用,因为它作为“开箱即用”功能更有意义,但一个相当简单的技巧是构建一个具有length 属性的类:

      class slist(list):
          @property
          def length(self):
              return len(self)
      

      你可以这样使用它:

      >>> l = slist(range(10))
      >>> l.length
      10
      >>> print l
      [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
      

      从本质上讲,它与列表对象完全相同,并具有对 OOP 友好的 length 属性的额外好处。

      与往常一样,您的里程可能会有所不同。

      【讨论】:

      • 只是告诉你,你可以只做length = property(len) 并跳过单行包装函数并将len 的文档/自省保存在你的财产中。
      【解决方案4】:

      除了len,您还可以使用operator.length_hint(需要Python 3.4+)。对于普通的list,两者是等价的,但length_hint 可以获取列表迭代器的长度,这在某些情况下可能很有用:

      >>> from operator import length_hint
      >>> l = ["apple", "orange", "banana"]
      >>> len(l)
      3
      >>> length_hint(l)
      3
      
      >>> list_iterator = iter(l)
      >>> len(list_iterator)
      TypeError: object of type 'list_iterator' has no len()
      >>> length_hint(list_iterator)
      3
      

      length_hint 根据定义只是一个“提示”,所以大多数时候len 更好。

      我看到了几个建议访问__len__ 的答案。这在处理像list 这样的内置类时没问题,但它可能会导致自定义类出现问题,因为len(和length_hint)实现了一些安全检查。例如,两者都不允许负长度或超过某个值(sys.maxsize 值)的长度。所以使用len 函数而不是__len__ 方法总是更安全!

      【讨论】:

        【解决方案5】:

        为了完整性(主要是教育性的),可以不使用len() 函数。我不会容忍这是一个好的选择不要在 PYTHON 中这样编程,但它可以用于学习算法。

        def count(list):
            item_count = 0
            for item in list[:]:
                item_count += 1
            return item_count
        
        count([1,2,3,4,5])
        

        list[:] 中带有冒号的索引操作是隐式的,因此也是可选的。)

        这里给新程序员的教训是:你不能在某个时候不计算列表中的项目数。问题变成了:什么时候是计算它们的好时机?例如,高性能代码,如用于套接字的 connect 系统调用(用 C 编写)connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen);,不会计算元素的长度(将责任交给调用代码)。注意到地址的长度是为了省去先计算长度的步骤而传递的吗?另一种选择:在计算上,在传递的对象中添加项目时跟踪项目的数量可能是有意义的。请注意,这会占用更多内存空间。见Naftuli Kay‘s answer

        跟踪长度以提高性能同时占用更多内存空间的示例。请注意,我从不使用 len() 函数,因为会跟踪长度:

        class MyList(object):
            def __init__(self):
                self._data = []
                self.length = 0 # length tracker that takes up memory but makes length op O(1) time
                
        
                # the implicit iterator in a list class
            def __iter__(self):
                for elem in self._data:
                    yield elem
                    
            def add(self, elem):
                self._data.append(elem)
                self.length += 1
                    
            def remove(self, elem):
                self._data.remove(elem)
                self.length -= 1
                    
        mylist = MyList()
        mylist.add(1)
        mylist.add(2)
        mylist.add(3)
        print(mylist.length) # 3
        mylist.remove(3)
        print(mylist.length) # 2
        

        【讨论】:

        • 为什么是for item in list[:]:?为什么不for item in list:?另外,我会使用+= 1 来增加。
        • @GrannyAching 我明确提到了可选的冒号(范围说明符)。出于教育目的,我将范围说明符留在那里 - 知道它是隐含的是有益的。正如您所建议的那样,还推断出列表类型 [] 与我的代码等效。增量运算符也相当于将 1 添加到现有变量,但在所有情况下都更短。因此,如果这是您的推理,我同意应该使用它。无论如何,这段代码不应该在任何地方投入生产(学习编程时除外)。
        • 如果我们要进入“不要这样做,但它很有趣”的兔子洞,我提供length = max(enumerate(list))[0] + 1
        • @KirkStrauser 哈哈,我对len() 上的这种巧妙回避笑了
        【解决方案6】:

        按照前面给出的例子回答你的问题:

        items = []
        items.append("apple")
        items.append("orange")
        items.append("banana")
        
        print items.__len__()
        

        【讨论】:

        • 在 Python 中,以下划线开头的名称在语义上是非公共方法,用户不应使用。
        • 1. __foo__:这只是一个约定,是 Python 系统使用不会与用户名冲突的名称的一种方式。 2._foo:这只是一个约定,是程序员指示变量是私有的(无论在 Python 中是什么意思)的一种方式。 3.__foo:这有实际意义:解释器用_classname__foo替换这个名字,以确保这个名字不会和另一个类中的相似名字重叠。 * 在 Python 世界中没有其他形式的下划线有意义。 * 在这些约定中,类、变量、全局等没有区别。
        • 这个问答解释了为什么你不应该作为用户直接使用特殊方法:stackoverflow.com/q/40272161/541136
        • @AaronHall 但对于 len 功能几乎相同。对于非常大的变量,它可能会更快。但是,我明白你的意思,我们应该使用 len(obj) 而不是 obj.__len__()。
        【解决方案7】:

        您可以使用len() 函数在python中查找可迭代的长度。

        my_list = [1, 2, 3, 4, 5]
        print(len(my_list))  # OUTPUT: 5
        

        len() 函数也适用于字符串:

        my_string = "hello"
        print(len(my_string))  # OUTPUT: 5
        

        总之,len() 适用于任何序列或集合(或定义__len__ 的任何大小的对象)。

        【讨论】:

          【解决方案8】:

          要获取任何顺序对象中的元素数量,您在 Python 中的 goto 方法是 len() 例如。

          a = range(1000) # range
          b = 'abcdefghijklmnopqrstuvwxyz' # string
          c = [10, 20, 30] # List
          d = (30, 40, 50, 60, 70) # tuple
          e = {11, 21, 31, 41} # set
          

          len() 方法可以处理上述所有数据类型,因为它们是可迭代的,即您可以迭代它们。

          all_var = [a, b, c, d, e] # All variables are stored to a list
          for var in all_var:
              print(len(var))
          

          len() 方法的粗略估计

          def len(iterable, /):
              total = 0
              for i in iterable:
                  total += 1
              return total
          

          【讨论】:

          • "any iterable" -- 这是不正确的。我认为您的意思是“任何序列”。生成器,例如:len(x for x in range(8)) -> TypeError: object of type 'generator' has no len().
          • 谢谢!这种generator也应该考虑。
          【解决方案9】:

          python 中有一个名为 len() 的内置函数,可以在这些情况下提供帮助。

          a=[1,2,3,4,5,6]
          print(len(a))     #Here the len() function counts the number of items in the list.
          

          输出:

          >>> 6
          

          这在字符串的情况下会略有不同(如下):

          a="Hello"
          print(len(a)) #Here the len() function counts the alphabets or characters in the list.
          

          输出:

          >>> 5
          

          这是因为变量(a)是一个字符串而不是一个列表,所以它会统计字符串中的字符或字母的个数,然后打印输出。

          【讨论】:

            【解决方案10】:

            len() 的实际工作方式而言,这是its C implementation

            static PyObject *
            builtin_len(PyObject *module, PyObject *obj)
            /*[clinic end generated code: output=fa7a270d314dfb6c input=bc55598da9e9c9b5]*/
            {
                Py_ssize_t res;
            
                res = PyObject_Size(obj);
                if (res < 0) {
                    assert(PyErr_Occurred());
                    return NULL;
                }
                return PyLong_FromSsize_t(res);
            }
            

            Py_ssize_t 是对象可以拥有的最大长度。 PyObject_Size() 是一个返回对象大小的函数。如果无法确定对象的大小,则返回 -1。在这种情况下,将执行此代码块:

                if (res < 0) {
                    assert(PyErr_Occurred());
                    return NULL;
                }
            

            结果引发了异常。否则,将执行此代码块:

                return PyLong_FromSsize_t(res);
            

            res 是一个 C 整数,被转换为 Python int(在 C 代码中仍称为“Long”,因为 Python 2 有两种用于存储整数的类型)并返回。

            【讨论】:

            • 为什么了解或了解 C 实现很重要?
            • 由于这个问题不是 CPython 特有的,所以这个答案可能会产生误导。 PyPy、IronPython... 可以并且确实以不同的方式实现它。
            • 这不是一个有用的答案,因为它只是说“len 调用PyObject_Size()”并没有说明它的作用,即“PyObject_Size()calls@987654324 @ 或 PyMapping_Size 在传入的对象上。"
            猜你喜欢
            • 2014-02-13
            • 1970-01-01
            • 1970-01-01
            • 2016-11-25
            • 2016-03-19
            • 2014-12-16
            • 1970-01-01
            • 2023-04-02
            • 1970-01-01
            相关资源
            最近更新 更多