Как мне узнать количество элементов в списке?


1938

Учтите следующее:

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

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

Как я могу получить количество элементов в списке items?


23
Вы явно спрашиваете количество элементов в списке. Если поисковик приходит сюда в поисках размера объекта в памяти, то это фактический вопрос и ответы, которые они ищут: Как определить размер объекта в Python?
Аарон Холл

Ответы:


2640

len()Функция может быть использована с несколькими различными типами в Python - как встроенные типы и библиотеки типов. Например:

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

Официальная документация 2.x здесь: Официальная документация 3.x здесь:len()
len()


239

Как получить размер списка?

Чтобы найти размер списка, используйте встроенную функцию len:

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

И сейчас:

len(items)

возвращает 3.

объяснение

Все в Python является объектом, включая списки. Все объекты имеют какой-то заголовок в C-реализации.

В частности, списки и другие подобные встроенные объекты с «размером» в Python имеют атрибут с именем ob_size, в котором кэшируется количество элементов в объекте. Поэтому проверка количества объектов в списке выполняется очень быстро.

Но если вы проверяете, равен ли размер списка нулю или нет, не используйте len- вместо этого поместите список в логический контекст - он будет считаться ложным, если пустым, в противном случае - истиной .

Из документов

len(s)

Вернуть длину (количество элементов) объекта. Аргумент может быть последовательностью (такой как строка, байты, кортеж, список или диапазон) или коллекцией (такой как словарь, набор или замороженный набор).

lenреализуется с помощью __len__из модели данных документов :

object.__len__(self)

Вызывается для реализации встроенной функции len(). Должен возвращать длину объекта, целое число> = 0. Кроме того, объект, который не определяет метод __nonzero__()[в Python 2 или __bool__()в Python 3] и чей __len__()метод возвращает ноль, считается ложным в логическом контексте.

И мы также можем видеть, что __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это более читабельно и более производительно.


75

Хотя это может быть бесполезно из-за того факта, что было бы гораздо более разумно использовать функциональность «из коробки», довольно простым способом было бы создать класс со 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свойства, удобного для ООП .

Как всегда, ваш пробег может отличаться.


19
просто чтобы вы знали, вы можете просто length = property(len)пропустить однострочную упаковочную функцию и сохранить документацию / самоанализ lenвашего свойства.
Тадхг Макдональд-Дженсен

17

Кроме того, 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, но это может привести к проблемам с пользовательскими классами, потому что lenlength_hint) реализовать некоторые проверки безопасности. Например, оба не допускают отрицательных длин или длин, которые превышают определенное значение ( sys.maxsizeзначение). Так что всегда безопаснее использовать lenфункцию вместо __len__метода!


8

Отвечая на ваш вопрос в качестве примеров, также приведенных ранее:

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

print items.__len__()

15
В Python имена, начинающиеся с подчеркивания, являются семантически закрытыми методами и не должны использоваться пользователями.
Аарон Холл

2
1 __foo__.: это просто соглашение, способ для системы Python использовать имена, которые не будут конфликтовать с именами пользователей. 2 _foo.: это просто соглашение, способ для программиста указать, что переменная является закрытой (что бы это ни значило в Python). 3 __foo.: это имеет реальное значение: интерпретатор заменяет это имя _classname__fooкак способ гарантировать, что имя не будет совпадать с аналогичным именем в другом классе. * Никакая другая форма подчеркивания не имеет значения в мире Python. * В этих соглашениях нет разницы между классом, переменной, глобальным и т. Д.
Шай Алон

4
В этом разделе «Вопросы и ответы» объясняется, почему вы не должны использовать специальные методы непосредственно как пользователь: stackoverflow.com/q/40272161/541136
Аарон Холл

@AaronHall, но для функции len это почти то же самое. Это может быть быстрее для очень больших переменных. Однако я понимаю вашу точку зрения, и мы должны использовать len (obj), а не obj .__ len __ ().
Шай Алон

7

А для полноты (в первую очередь образовательной) это возможно без использования len()функции. Я не одобрил бы это как хороший вариант. НЕ ПРОГРАММИРУЙТЕ, КАК ЭТО ТАКОЕ В ПИТОНЕ , но он служит цели для изучения алгоритмов.

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);, не рассчитывает длину элементов (возлагая эту ответственность на вызывающий код). Заметьте, что длина адреса передается, чтобы сохранить шаг подсчета длины в первую очередь? Другой вариант: в вычислительном отношении может иметь смысл отслеживать количество элементов по мере их добавления в передаваемый объект. Имейте в виду, что это занимает больше места в памяти. Смотрите ответ Нафтули Кея .

Пример отслеживания длины для улучшения производительности, занимая больше места в памяти. Обратите внимание, что я никогда не использую функцию 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 к существующей переменной, но во всех случаях короче. Так что я бы согласился, что это следует использовать, если это ваше мнение. Этот код не должен быть запущен в любом месте, в любом случае (кроме как при изучении программирования).
Джонатан Комар

0

С точки зрения того, как на len()самом деле работает, это его реализация C :

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целым числом, конвертируется в питон longи возвращается. Все целые числа Python хранятся как longsначиная с Python 3.


3
Почему знание или знание о реализации C имеет значение?
cs95

Поскольку этот вопрос не является специфичным для CPython, этот ответ может вводить в заблуждение. PyPy, IronPython, ... могут и делают это по-разному.
MSeifert

-2

Здесь вам нужна длина списка, поэтому для вычисления используйте простую функцию len ().

A=[1,2,3,4,5]
print(len(A))
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.