Чи є arr .__ len __ () кращим способом отримати довжину масиву в Python?


Відповіді:


1228
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)

8
len () - це мовна команда, __len __ () - метод для типів контейнерів.
Радянський

33
len () - глобальна, вбудована функція; __len __ () - метод, який об'єкт може реалізувати. len (foo) зазвичай закінчується викликом foo .__ len __ ().
Тім Лешер

13
Ви згадуєте, що, постачаючи len (), кожен контейнер не повинен реалізувати. Чи різні типи контейнерів по-різному обробляються len ()?
Simon B. Jensen

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в ці екземпляри.


23

Python використовує качиної типізації : він не піклується про те, що об'єкт знаходиться , до тих пір , як він має відповідний інтерфейс для конкретної ситуації. Коли ви викликаєте вбудовану функцію len () на об'єкті, ви фактично викликаєте його внутрішній метод __len__. Спеціальний об'єкт може реалізувати цей інтерфейс, а len () поверне відповідь, навіть якщо об'єкт не є концептуальною послідовністю.

Повний список інтерфейсів див. Тут: http://docs.python.org/reference/datamodel.html#basic-customization


23

Кращий спосіб отримати довжину будь-якого об’єкта python - це передавати його як аргумент lenфункції. Потім внутрішньо пітон спробує викликати спеціальний __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повернення висоти та ширини



1

Python пропонує користувачам використовувати len()замість __len__()консистенції, як і інші хлопці. Однак є й інші переваги:

Для деяких вбудованих типів , таких як list, str, bytearrayі так далі, реалізація Cython з len()займає ярлик. Він безпосередньо повертає ob_sizeструктуру C, що швидше, ніж виклик __len__().

Якщо вас цікавлять такі подробиці, ви можете прочитати книгу Лучано Рамальо під назвою "Плавний пітон". У ньому багато цікавих деталей, і вони можуть допомогти вам глибше зрозуміти Python.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.