Розглянемо наступне:
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властивість, сприятливу для OOP .
Як завжди, пробіг може відрізнятися.
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(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.