Является ли arr .__ len __ () предпочтительным способом получения длины массива в Python?

728

В Python , следующий ли единственный способ получить количество элементов?

arr.__len__()

Если так, то почему странный синтаксис?

Джоан Венге
источник

Ответы:

1229
my_list = [1,2,3,4,5]
len(my_list)
# 5

То же самое работает для кортежей:

my_tuple = (1,2,3,4,5)
len(my_tuple)
# 5

И строки, которые на самом деле являются просто массивами символов:

my_string = 'hello world'
len(my_string)
# 11

Это было сделано намеренно таким образом, чтобы списки, кортежи и другие типы контейнеров или итераций не требовали явной реализации открытого .length()метода, вместо этого вы можете просто проверить len()все, что реализует «магический» __len__()метод.

Конечно, это может показаться излишним, но реализации проверки длины могут значительно различаться даже в пределах одного языка. Часто один тип коллекции использует .length()метод, в то время как другой тип использует .lengthсвойство, в то время как другой использует .count(). Наличие ключевого слова на уровне языка объединяет точку входа для всех этих типов. Таким образом, даже объекты, которые вы не считаете списками элементов, все же могут быть проверены по длине. Это включает в себя строки, очереди, деревья и т. Д.

Функциональная природа len()также хорошо подходит для функциональных стилей программирования.

lengths = map(len, list_of_containers)
Soviut
источник
8
len () - это языковая команда, __len __ () - метод для типов контейнеров.
Совют
33
len () - глобальная встроенная функция; __len __ () - это метод, который объект может реализовать. len (foo) обычно заканчивает тем, что вызывает foo .__ len __ ().
Тим Лешер
13
Вы упоминаете, что, предоставляя len (), каждый контейнер не должен реализовывать метод .length (), но как это отличается, если каждый тип все еще реализует метод __len __ (), который в любом случае вызывается len ()? Len () по-разному обрабатывает разные типы контейнеров?
Саймон Б. Дженсен
10
@Simon: немного о том, «не всем нужно реализовывать .length ()», сбивает с толку. Контейнерные типы все еще должны реализовать метод для возврата их длины; Дело в том, что это стандартный протокол, а не специальный метод, который вы должны искать для каждого типа. Двойные подчеркивания означают это.
Карл Мейер
16
Я согласен с Карлом Мейером - говорить, что «не нужно явно реализовывать» публичный метод .length (), вводит в заблуждение и, по сути, неверно. Все, что еще нужно реализовать len , всегда может просто реализовать свой собственный метод длины, названный так, как он хочет, - обходя функцию len. Так что на самом деле я вижу в этом какую-то странную странность, которая соответствует тому, как Гвидо видит мир. Это, вероятно, не имеет ничего общего с универсальными рассуждениями.
BT
52

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

l = [1,2,3,4]
s = 'abcde'
len(l) #returns 4
len(s) #returns 5

Причина "странного" синтаксиса в том, что внутренне Python переводит len(object) в object.__len__(). Это относится к любому объекту. Итак, если вы определяете некоторый класс, и для него имеет смысл иметь длину, просто определите для него __len__()метод, и тогда можно будет вызывать lenэти экземпляры.

RZ.
источник
23

Python использует утиной типизации : он не заботится о том, что объект является , до тех пор , как он имеет соответствующий интерфейс для конкретной ситуации. Когда вы вызываете встроенную функцию len () для объекта, вы фактически вызываете его внутренний метод __len__. Пользовательский объект может реализовать этот интерфейс, и len () вернет ответ, даже если объект концептуально не является последовательностью.

Полный список интерфейсов можно найти здесь: http://docs.python.org/reference/datamodel.html#basic-customization.

UncleZeiv
источник
23

Предпочтительный способ получить длину любого объекта python - передать его в качестве аргумента lenфункции. Внутри себя python попытается вызвать специальный __len__метод переданного объекта.

Дэвид Лок
источник
22

Просто используйте len(arr):

>>> import array
>>> arr = array.array('i')
>>> arr.append('2')
>>> arr.__len__()
1
>>> len(arr)
1
Тим Лешер
источник
10

Вы можете использовать, len(arr) как предложено в предыдущих ответах, чтобы получить длину массива. Если вам нужны размеры 2D-массива, вы можете использовать arr.shapeвозвращаемые значения высоты и ширины.

Ахмед Абобакр
источник
7

len(list_name)Функция принимает список в качестве параметра и вызывает __len__()функцию списка .

Харун ЭРГУЛ
источник
1

Python предлагает пользователям использовать len()вместо __len__()согласованности, как говорили другие парни. Однако есть и другие преимущества:

Для некоторых встроенных типов , таких как list, str, bytearrayи так далее, реализация Cython из len()занимает ярлык. Он напрямую возвращает ob_sizeструктуру C, которая быстрее, чем вызов __len__().

Если вас интересуют такие детали, вы можете прочитать книгу Лучано Рамалхо под названием «Свободный питон». В нем много интересных деталей, которые могут помочь вам глубже понять Python.

JOHNKYON
источник