Почему код Python использует функцию len() вместо метода length?

StackOverflow https://stackoverflow.com/questions/237128

Вопрос

Я знаю, что в python есть len() функция, которая используется для определения размера строки, но мне было интересно, почему это не метод объекта string.

Обновить

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

Это было полезно?

Решение

У строк действительно есть метод длины: __len__()

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

Видишь Эмулирующие типы контейнеров для получения дополнительной информации.

Вот хорошая статья на тему протоколов в Python: Python и принцип наименьшего удивления

Другие советы

Ответ Джима на этот вопрос может помочь;Я копирую это здесь.Цитирую Гвидо ван Россума:

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

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

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

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

Существует len способ:

>>> a = 'a string of some length'
>>> a.__len__()
23
>>> a.__len__
<method-wrapper '__len__' of str object at 0x02005650>

Python - это прагматичный язык программирования, и причины для len() являясь функцией, а не методом str, list, dict и т.д.являются прагматичными.

Тот самый len() встроенная функция имеет дело непосредственно со встроенными типами:реализация CPython для len() фактически возвращает значение ob_size поле в PyVarObject Структура C это представляет собой любой встроенный объект переменного размера в памяти.Это многое быстрее, чем вызов метода - поиск атрибутов не требуется.Получение количества элементов в коллекции является обычной операцией и должно эффективно работать для таких базовых и разнообразных типов, как str, list, array.array и т.д.

Однако для обеспечения согласованности при нанесении len(o) для определенного пользователем типа Python вызывает o.__len__() в качестве запасного варианта. __len__, __abs__ и все другие специальные методы, задокументированные в Модель данных Python упростите создание объектов, которые ведут себя подобно встроенным компонентам, используя выразительные и высокосогласованные API, которые мы называем "Pythonic".

Реализуя специальные методы, ваши объекты могут поддерживать итерацию, перегружать инфиксные операторы, управлять контекстами в with блоки и т.д.Вы можете рассматривать модель данных как способ использования самого языка Python в качестве фреймворка, в котором создаваемые вами объекты могут быть легко интегрированы.

Вторая причина, подкрепленная цитатами из Гвидо ван Россума, такими как этот, заключается в том , что его легче читать и писать len(s) чем s.len().

Обозначение len(s) согласуется с унарными операторами с префиксной нотацией, например abs(n). len() используется намного чаще, чем abs(), и она заслуживает того, чтобы ее было так же легко написать.

Также может быть историческая причина:в языке ABC, который предшествовал Python (и оказал большое влияние на его дизайн), существовал унарный оператор, записанный как #s что означало len(s).

met% python -c 'import this' | grep 'only one'
There should be one-- and preferably only one --obvious way to do it.

Здесь есть несколько отличных ответов, и поэтому, прежде чем я дам свой собственный, я хотел бы выделить несколько драгоценных камней (без каламбура ruby) Я прочитал здесь.

  • Python не является чистым языком ООП - это универсальный многопарадигмальный язык, который позволяет программисту использовать ту парадигму, с которой ему наиболее комфортно, и / или ту парадигму, которая лучше всего подходит для его решения.
  • Python обладает первоклассными функциями, так что len на самом деле это объект.Ruby, с другой стороны, не имеет функций первого класса.Таким образом, len объект функции имеет свои собственные методы, которые вы можете проверить, запустив dir(len).

Если вам не нравится, как это работает в вашем собственном коде, для вас тривиально повторно реализовать контейнеры, используя ваш предпочтительный метод (см. Пример ниже).

>>> class List(list):
...     def len(self):
...         return len(self)
...
>>> class Dict(dict):
...     def len(self):
...         return len(self)
...
>>> class Tuple(tuple):
...     def len(self):
...         return len(self)
...
>>> class Set(set):
...     def len(self):
...         return len(self)
...
>>> my_list = List([1,2,3,4,5,6,7,8,9,'A','B','C','D','E','F'])
>>> my_dict = Dict({'key': 'value', 'site': 'stackoverflow'})
>>> my_set = Set({1,2,3,4,5,6,7,8,9,'A','B','C','D','E','F'})
>>> my_tuple = Tuple((1,2,3,4,5,6,7,8,9,'A','B','C','D','E','F'))
>>> my_containers = Tuple((my_list, my_dict, my_set, my_tuple))
>>>
>>> for container in my_containers:
...     print container.len()
...
15
2
15
15

Вы также можете сказать

>> x = 'test'
>> len(x)
4

Использование Python 2.7.3.

Это не так?

>>> "abc".__len__()
3
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top