Учтите следующее:
items = []
items.append("apple")
items.append("orange")
items.append("banana")
# FAKE METHOD:
items.amount() # Should return 3
Как я могу получить количество элементов в списке items
?
Учтите следующее:
items = []
items.append("apple")
items.append("orange")
items.append("banana")
# FAKE METHOD:
items.amount() # Should return 3
Как я могу получить количество элементов в списке items
?
Ответы:
Как получить размер списка?
Чтобы найти размер списка, используйте встроенную функцию 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
это более читабельно и более производительно.
Хотя это может быть бесполезно из-за того факта, что было бы гораздо более разумно использовать функциональность «из коробки», довольно простым способом было бы создать класс со 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
вашего свойства.
Кроме того, 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__
метода!
Отвечая на ваш вопрос в качестве примеров, также приведенных ранее:
items = []
items.append("apple")
items.append("orange")
items.append("banana")
print items.__len__()
__foo__
.: это просто соглашение, способ для системы Python использовать имена, которые не будут конфликтовать с именами пользователей. 2 _foo
.: это просто соглашение, способ для программиста указать, что переменная является закрытой (что бы это ни значило в Python). 3 __foo
.: это имеет реальное значение: интерпретатор заменяет это имя _classname__foo
как способ гарантировать, что имя не будет совпадать с аналогичным именем в другом классе. * Никакая другая форма подчеркивания не имеет значения в мире Python. * В этих соглашениях нет разницы между классом, переменной, глобальным и т. Д.
А для полноты (в первую очередь образовательной) это возможно без использования 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
для увеличения.
С точки зрения того, как на 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.