Разница между LEN() и. лен ()?


есть ли разница между вызовом len([1,2,3]) или [1,2,3].__len__()?

Если нет видимой разницы, что делается по-другому-за кулис?

4 69

4 ответа:

len - Это функция для получения длины коллекции. Он работает путем вызова объекта __len__ метод. __something__ атрибуты являются особыми и обычно больше, чем кажется на первый взгляд, и, как правило, не должны вызываться напрямую.

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

часто бывает так, что "типичное" поведение встроенного или оператора заключается в вызове (с другим и более приятным синтаксисом) подходящих магических методов (с такими именами, как __whatever__) на задействованных объектах. Часто встроенный или оператор имеет "добавленную стоимость" (он может принимать разные пути в зависимости от задействованных объектов) -- в случае len vs __len__, это просто немного здравомыслия проверка на встроенный, который отсутствует в волшебном методе:

>>> class bah(object):
...   def __len__(self): return "an inch"
... 
>>> bah().__len__()
'an inch'
>>> len(bah())
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: 'str' object cannot be interpreted as an integer

когда вы смотрите звонок в len встроенный, ты обязательно что, если программа продолжает после этого, а не вызывает исключение, вызов вернул целое число, неотрицательное и менее 2* * 31 -- Когда вы видите вызов xxx.__len__(), у вас нет уверенности (за исключением того, что автор кода либо не знаком с Python, либо не подходит;-).

другие встроенные модули обеспечивают еще большую добавленную стоимость за простой проверки здравомыслия и удобочитаемости. Путем равномерно конструировать все из Python для работы с помощью вызовов builtins и использования операторов, никогда не вызывая магические методы, программисты избавлены от бремени запоминания того, какой случай есть. (Иногда ошибка проскальзывает: до 2.5, вы должны были позвонить foo.next() -- в 2.6, хотя это все еще работает для обратной совместимости, вы должны позвонить next(foo) и 3.*, магический метод правильно назван __next__ вместо "ой-ей" next!-).

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

вы можете думать о len () как о примерно эквивалентном

def len(x):
    return x.__len__()

одним из преимуществ является то, что он позволяет писать такие вещи, как

somelist = [[1], [2, 3], [4, 5, 6]]
map(len, somelist) 

вместо

map(list.__len__, somelist)

или

map(operator.methodcaller('__len__'), somelist)

есть немного другое поведение, хотя. Например, в случае ints

>>> (1).__len__()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'int' object has no attribute '__len__'
>>> len(1)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: object of type 'int' has no len()

вы можете проверить Pythond docs:

>>> class Meta(type):
...    def __getattribute__(*args):
...       print "Metaclass getattribute invoked"
...       return type.__getattribute__(*args)
...
>>> class C(object):
...     __metaclass__ = Meta
...     def __len__(self):
...         return 10
...     def __getattribute__(*args):
...         print "Class getattribute invoked"
...         return object.__getattribute__(*args)
...
>>> c = C()
>>> c.__len__()                 # Explicit lookup via instance
Class getattribute invoked
10
>>> type(c).__len__(c)          # Explicit lookup via type
Metaclass getattribute invoked
10
>>> len(c)                      # Implicit lookup
10