Я знаю, что в python есть len()
функция, которая используется для определения размера строки, но мне было интересно, почему это не метод объекта string.
Обновить
Хорошо, я понял, что я смущенно ошибался. __len__()
на самом деле метод строкового объекта. Просто кажется странным видеть объектно-ориентированный код в Python, использующий функцию len для строковых объектов. Кроме того, это также странно видеть __len__
как имя, а не просто len.
len(someObj)
не называетsomeObj
«s__len__
функции? tl; dr Да, поэтому всегда используйтеlen()
вместо__len__()
.Ответы:
Строки имеют метод длины:
__len__()
Протокол в Python состоит в том, чтобы реализовать этот метод на объектах, которые имеют длину и используют встроенную
len()
функцию, которая вызывает ее для вас, подобно тому, как вы реализуете__iter__()
и используете встроеннуюiter()
функцию (или вызываете метод позади). сцены для вас) на объектах, которые являются повторяемыми.См. Эмуляция типов контейнеров для получения дополнительной информации.
Вот хорошее прочтение на тему протоколов в Python: Python и принцип наименьшего удивления
источник
len
. Они думают, что легче заставить людей осуществлять,.__len__
чем заставлять людей выполнять.len()
. Это то же самое, и каждый выглядит намного чище. Если у языка будет ООП__len__
, в чем смысл создания мираlen(..)
__iter__
или только с помощью__getitem__
иiter(x)
работать в любом случае. Вы можете создать объект in-bool-context с помощью__bool__
или__len__
иbool(x)
работать в любом случае. И так далее. Я думаю, что Армин достаточно хорошо объясняет это в связанном посте, но даже если бы он этого не сделал, называть Python дебильным из-за внешнего объяснения парня, который часто публично расходится с основными разработчиками, было бы не совсем справедливо…zip
это функция верхнего уровня, а неzip_with
метод. И так далее. То, что все является объектом, не означает, что быть объектом - это самое важное в каждой вещи.Ответ Джима на этот вопрос может помочь; Я копирую это здесь. Цитируя Гвидо ван Россума:
источник
Есть
len
метод:источник
len
проверяет вывод__len__
. См Есть ли случай , когдаlen(someObj)
не называетsomeObj
«s__len__
функции? Методы Dunder в целом не предназначены для непосредственного вызова.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)
.источник
источник
Здесь есть несколько отличных ответов, и поэтому прежде чем дать свой, я бы хотел выделить несколько драгоценных камней (без рубиновой каламбуры), которые я читал здесь.
len
на самом деле это объект. Ruby, с другой стороны, не имеет функций первого класса. Таким образом, уlen
объекта функции есть свои собственные методы, которые вы можете проверить, запустивdir(len)
.Если вам не нравится, как это работает в вашем собственном коде, для вас тривиально повторно реализовать контейнеры, используя ваш предпочтительный метод (см. Пример ниже).
источник
Чего-то не хватает в остальных ответах здесь:
len
функция проверяет, что__len__
метод возвращает неотрицательное значениеint
. Тот факт, чтоlen
это функция, означает, что классы не могут переопределить это поведение, чтобы избежать проверки. Как таковой,len(obj)
дает уровень безопасности, которыйobj.len()
не может.Пример:
Конечно, можно «переопределить»
len
функцию, переназначив ее как глобальную переменную, но код, который делает это, гораздо более подозрительно, чем код, который переопределяет метод в классе.источник
sys.maxsize
, и чтоobj.__len__
существует в первую очередь. Я написал ответ на другой вопрос, в котором перечислены все различные проверки.Вы также можете сказать
Использование Python 2.7.3.
источник
len
функция уже упоминалась в предыдущих ответах. Какой смысл в этом "ответе"?Это не так?
источник
len(someObj)
не называетsomeObj
«s__len__
функции? Методы Dunder в целом не предназначены для непосредственного вызова.