Почему функция "len" не унаследована словарями и списками в Python

Пример:

a_list = [1, 2, 3]
a_list.len() # doesn't work
len(a_list) # works

Python (очень) объектно-ориентированный, я не понимаю, почему функция len не наследуется объектом. Плюс я продолжаю пытаться ошибочное решение, поскольку оно кажется мне логичным

Ответ 1

Объяснение Guido здесь:

Прежде всего, я выбрал len (x) по x.len() по причинам HCI (def __len __() появился намного позже). На самом деле есть две взаимосвязанные причины: и HCI:

(a) Для некоторых операций префиксная нотация только читается лучше, чем операции postfix - prefix (и infix!), имеют давнюю традицию в математике, которая любит записи, где визуальные эффекты помогают математику думать о проблеме. Сравните простоту, с которой мы переписываем формулу, такую ​​как x * (a + b), в xa + xb, к неуклюжести того же самого действия, используя необработанную нотацию OO.

(b) Когда я читаю код, который говорит len (x), я знаю, что он просит длину чего-то. Это говорит мне две вещи: результат - целое число, а аргумент - это какой-то контейнер. Напротив, когда я читаю x.len(), я должен уже знать, что x - это какой-то контейнер, реализующий интерфейс или наследующий от класса, который имеет стандартный len(). Свидетельствуйте путаницу, которую мы иногда испытываем, когда класс, который не реализует сопоставление, имеет метод get() или keys() или что-то, что не является файлом, имеет метод write().

Говоря то же самое по-другому, я вижу "len" как встроенную операцию. Я ненавижу потерять это. /.../

Ответ 2

Короткий ответ: 1) обратная совместимость и 2) для этого не существует существенной разницы. Для более подробного объяснения читайте дальше.

Идиоматический подход Python к таким операциям - это специальные методы, которые не предназначены для прямого вызова. Например, чтобы сделать x + y работать для вашего собственного класса, вы пишете метод __add__. Чтобы убедиться, что int(spam) правильно преобразовывает ваш собственный класс, напишите метод __int__. Чтобы убедиться, что len(foo) делает что-то разумное, напишите метод __len__.

Так всегда было с Python, и я думаю, что это имеет много смысла для некоторых вещей. В частности, это кажется разумным способом реализации перегрузки оператора. Что касается остальных, разные языки не согласны; в Ruby вы конвертируете что-то в целое число, вызывая spam.to_i напрямую, а не говоря int(spam).

Вы правы, что Python является чрезвычайно объектно-ориентированным языком и что вызов внешней функции объекта для получения его длины кажется странным. С другой стороны, len(silly_walks) не является более обременительным, чем silly_walks.len(), и Гвидо сказал, что он действительно предпочитает его (http://mail.python.org/pipermail/python-3000/2006-November/004643.html).

Ответ 3

Это просто не так.

Однако вы можете:

>>> [1,2,3].__len__()

3

Добавление метода __len__() в класс - это то, что делает магию len().

Ответ 4

Этот способ лучше подходит для остальной части языка. Соглашение в python заключается в том, что вы добавляете специальные методы __foo__ к объектам, чтобы они имели определенные возможности (а не, например, исходя из определенного базового класса). Например, объект

  • вызываемый, если он имеет метод __call__
  • iterable, если он имеет метод __iter__,
  • поддерживает доступ с помощью [], если он имеет __getitem__ и __setitem__.
  • ...

Один из этих специальных методов - __len__, который позволяет иметь длину, доступную с помощью len().

Ответ 5

Возможно, вы ищете __len__. Если этот метод существует, то len (a) вызывает его:

>>> class Spam:
...   def __len__(self): return 3
... 
>>> s = Spam()
>>> len(s)
3

Ответ 6

Ну, на самом деле существует метод длины, он просто скрыт:

>>> a_list = [1, 2, 3]
>>> a_list.__len__()
3

Встроенная функция len() представляется просто оболочкой для вызова скрытого метода len() объекта.

Не уверен, почему они приняли решение реализовать вещи таким образом, хотя.

Ответ 7

есть некоторая хорошая информация ниже о том, почему определенные вещи являются функциями, а другие - методами. Это действительно вызывает некоторые несоответствия в языке.

http://mail.python.org/pipermail/python-dev/2008-January/076612.html