Есть ли причина, по которой строки Python не имеют метода длины строки?

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

Обновление

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

Ответ 1

Строки имеют метод длины: __len__()

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

Подробнее см. Эмуляция типов контейнеров.

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

Ответ 2

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

Прежде всего, я выбрал 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" как встроенную операцию. Я ненавижу потерять это. /.../

Ответ 3

Существует метод len:

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

Ответ 4

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

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

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

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

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

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

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

Ответ 5

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

Ответ 6

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

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

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

Ответ 7

Это не так?

>>> "abc".__len__()
3

Ответ 8

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

  • Python не является чистым языком OOP - это универсальный язык с несколькими парадигмами, который позволяет программисту использовать парадигму, которой они наиболее удобны, и/или парадигму, которая лучше всего подходит для их решения.
  • Функции имеют первоклассные функции, поэтому 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