如何获取列表items
中元素的数量?
items = ["apple", "orange", "banana"]
# There are 3 items.
len
:items = []
items.append("apple")
items.append("orange")
items.append("banana")
现在:
len(items)
返回3。
Python中的所有东西都是对象,包括列表。所有对象在C实现中都有某种类型的头文件。
列表和其他类似的内置对象在Python中具有“大小”,特别是具有称为ob_size
的属性,其中缓存了对象中元素的数量。因此,检查列表中的对象数量非常快。
但是,如果您要检查列表大小是否为零,请不要使用len
- 相反,将列表放入布尔上下文中 - 如果为空,则将其视为False;如果非空,则将其视为True。
len(s)
返回对象的长度(项目数)。参数可以是序列(例如字符串、字节、元组、列表或范围)或集合(例如字典、集合或冻结集合)。
len
是使用数据模型中的 __len__
实现的,具体请参考 docs:
object.__len__(self)
len()
。 应返回对象的长度,一个整数>= 0。 另外,在布尔上下文中,如果一个对象没有定义__nonzero__()
[在Python 2中]或者__bool__()
[在Python 3中]方法,并且其__len__()
方法返回零,则被视为false。__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!
...
我在这里解释原因,但简而言之,if items
或if not items
比其他替代方案更易读且性能更好。
虽然这可能并不实用,因为它更适合作为“开箱即用”的功能,但是一个相当简单的hack是构建一个具有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]
本质上,它与列表对象完全相同,具有面向对象编程友好的length
属性的额外好处。
一如既往,您的结果可能会有所不同。
length = property(len)
来代替一行包装函数,这样做可以保留len
函数的文档和内省功能,并使代码更简洁易懂。 - Tadhg McDonald-Jensen除了使用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
函数!
为了完整起见(主要是教育目的),可以不使用len()
函数来实现。我不认为这是一个好选择,不要用Python编写这样的程序,但对于学习算法有一定的作用。
def count(list): # list is an iterable object but no type checking here!
item_count = 0
for item in list:
item_count += 1
return item_count
count([1,2,3,4,5])
(列表对象必须是可迭代的,这由for..in
语句暗示。)
新程序员需要了解的教训是:你无法在不计数的情况下获取列表中的项目数量。问题是:什么时候计数最好?例如,像C语言中编写的套接字的connect系统调用 connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
这样的高性能代码并不计算元素的长度(将这个责任交给调用代码)。请注意,地址的长度被传递以节省首先计算长度的步骤。另一个选项:从计算的角度来看,在你传递的对象内添加项目时跟踪它们的数量可能是有意义的。但要注意,这会占用更多的内存空间。参见Naftuli Kay的答案。
以下是跟踪长度以提高性能并占用更多内存空间的示例。请注意,我从未使用过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
进行递增。 - Granny Achinglength = max(enumerate(list))[0] + 1
。 - Kirk Strauserlen()
而笑了。 - Jonathan Komarlist[:]
中的[:]
不是“范围指定符”,而是切片,它会浅复制整个list
,没有任何理由。如果省略了[:]
,它就不会执行任何这样浪费的复制;知道它被隐含了并没有什么好处,因为它根本就没有被隐含。我不知道“列表类型[]也被推断出来”是什么意思,但没有推断类型;对象有类型,任何满足你所做的鸭子类型要求的东西都将被接受(无论是list
、tuple
、str
等)。 - ShadowRanger回答您的问题,如之前给出的示例:
items = []
items.append("apple")
items.append("orange")
items.append("banana")
print items.__len__()
__foo__
:这只是一种约定,Python 系统使用这种方式来使用名称,以避免与用户名称冲突。_foo
:这只是一种约定,程序员用来表示变量是私有的(无论在 Python 中意味着什么)。__foo
:这具有实际意义:解释器将此名称替换为 _classname__foo
,以确保该名称不会与另一个类中的类似名称重叠。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__
的任何大小对象)一起使用。你可以通过三种方法来查找列表中元素的长度。我将在此处使用性能分析比较这3种方法。
len()
items = []
items.append("apple")
items.append("orange")
items.append("banana")
print(len(items))
输出:
3
items = []
items.append("apple")
items.append("orange")
items.append("banana")
counter = 0
for i in items:
counter = counter + 1
print(counter)
输出:
3
length_hint()
items = []
items.append("apple")
items.append("orange")
items.append("banana")
from operator import length_hint
list_len_hint = length_hint(items)
print(list_len_hint)
输出:
3
len()
vs length_hint()
注意:为了进行比较,我将输入列表更改为一个大的集合,以便比较这些方法的时间差异。
items = list(range(100000000))
# Performance Analysis
from operator import length_hint
import time
# Finding length of list
# using loop
# Initializing counter
start_time_naive = time.time()
counter = 0
for i in items:
# incrementing counter
counter = counter + 1
end_time_naive = str(time.time() - start_time_naive)
# Finding length of list
# using len()
start_time_len = time.time()
list_len = len(items)
end_time_len = str(time.time() - start_time_len)
# Finding length of list
# using length_hint()
start_time_hint = time.time()
list_len_hint = length_hint(items)
end_time_hint = str(time.time() - start_time_hint)
# Printing Times of each
print("Time taken using naive method is : " + end_time_naive)
print("Time taken using len() is : " + end_time_len)
print("Time taken using length_hint() is : " + end_time_hint)
输出:
Time taken using naive method is : 7.536813735961914
Time taken using len() is : 0.0
Time taken using length_hint() is : 0.0
可以清楚地看到,与其他两种方法相比,naive所需的时间非常长,因此len()
和length_hint()
是最好的选择。
time.time()
计时一次执行?学习使用timeit
模块;有如此多的混淆变量,以至于除了“循环和计数较慢”之外,无法从您的测试中得出任何结论。 - ShadowRanger>>> a = [1,2,3,4,5,6]
>>> len(a) # Here the len() function counts the number of items in the list.
6
对于字符串来说,情况会略有不同:它计算的是字符数。
>>> a = "Hello"
>>> len(a)
5
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
len(x for x in range(8))
-> TypeError: object of type 'generator' has no len()
。 - wjandreaset
和dict
上运行得非常好(两者都不是序列)。 - ShadowRangercollections.abc
,那么任何Sequence
都是根据定义一个Collection
,但我们只需要一个Sized
对象来获取其长度。因此,我认为为了这个答案的缘故,最好说“任何对象”,避免过于复杂化事情。 - wjandrealen()
方法适用于那些数据类型,并不是因为它们是可迭代的,而是因为它们有一个 __len__()
方法,也就是说它们有一个预先知道的大小,在迭代之前就已经确定了。而且我不确定当它实际上在任何(有限的)可迭代对象上工作时,那个粗略的估计有多有用。 - wjandrea