问题:如何获取列表中的元素数量?
考虑以下:
items = []
items.append("apple")
items.append("orange")
items.append("banana")
# FAKE METHOD:
items.amount() # Should return 3
如何获取列表中的元素数量items
?
回答 0
回答 1
如何获得列表的大小?
要查找列表的大小,请使用内置函数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__
,从数据模型文档:
object.__len__(self)
调用以实现内置函数
len()
。应该返回对象的长度,即> = 0的整数。而且,在Boolean上下文中,未定义__nonzero__()
[在Python 2或__bool__()
Python 3中]方法且其__len__()
方法返回零的对象被视为false。
我们还可以看到这__len__
是一种列表方法:
items.__len__()
返回3。
内建类型,你可以得到len
的(长)
实际上,我们看到我们可以为所有描述的类型获取此信息:
>>> all(hasattr(cls, '__len__') for cls in (str, bytes, tuple, list,
xrange, 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
更具可读性和性能。
回答 2
虽然由于“开箱即用”功能在意义上更有意义,所以这可能没有用,但是一个相当简单的技巧是使用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
属性。
和往常一样,您的里程可能会有所不同。
回答 3
此外,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__
方法总是更安全!
回答 4
通过前面给出的示例来回答您的问题:
items = []
items.append("apple")
items.append("orange")
items.append("banana")
print items.__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[:]
是隐式的,因此也是可选的。)
对于新程序员来说,这里的教训是:您无法在不计算点的情况下获得列表中的项目数。问题就变成了:什么时候该计数它们呢?例如,诸如套接字的连接系统调用之类的高性能代码(用C编写)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
回答 6
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 long
并返回。longs
自python 3起,所有python整数都存储。