Difference Between Len() and ._Len_()

Difference between len() and .__len__()?

len is a function to get the length of a collection. It works by calling an object's __len__ method. __something__ attributes are special and usually more than meets the eye, and generally should not be called directly.

It was decided at some point long ago getting the length of something should be a function and not a method code, reasoning that len(a)'s meaning would be clear to beginners but a.len() would not be as clear. When Python started __len__ didn't even exist and len was a special thing that worked with a few types of objects. Whether or not the situation this leaves us makes total sense, it's here to stay.

Using len() and def __len__(self): to build a class

There is a huge difference.

The __len__() method is a hook method. The len() function will use the __len__ method if present to query your object for it's length.

The normal API people expect to use is the len() method, using a .len attribute instead would deviate from that norm.

If the length of self.data is not expected to change, you can always cache the length in an attribute and have .__len__() return that attribute.

class foo(object):
def __init__(self, obs=None):
if obs is None: # provide a default if no list was passed in.
obs = []
self.data = obs
self.max = max(obs)
self.min = min(obs)
self._data_len = len(obs)

def __len__(self):
return self._data_len

Why is Python's 'len' function faster than the __len__ method?

The builtin len() function does not look up the .__len__ attribute. It looks up the tp_as_sequence pointer, which in turn has a sq_length attribute.

The .__len__ attribute on built-in objects is indirectly mapped to the same slot, and it is that indirection (plus the attribute lookup) that takes more time.

For Python-defined classes, the type object looks up the .__len__ method when the sq_length is requested.

What is the difference between len() and count() in python?

list.count() counts how many times the given value appears. You created a list of 5 elements that are all the same, so of course x_list.count() finds that element 5 times in a list of length 5.

You could have tried the same test with a list with a mix of values:

>>> sample = [2, 10, 1, 1, 5, 2]
>>> len(sample)
6
>>> sample.count(1)
2

The sample list contains 6 elements, but the value 1 appears only twice.

Understanding __getitem__ method

Cong Ma does a good job of explaining what __getitem__ is used for - but I want to give you an example which might be useful.
Imagine a class which models a building. Within the data for the building it includes a number of attributes, including descriptions of the companies that occupy each floor :

Without using __getitem__ we would have a class like this :

class Building(object):
def __init__(self, floors):
self._floors = [None]*floors
def occupy(self, floor_number, data):
self._floors[floor_number] = data
def get_floor_data(self, floor_number):
return self._floors[floor_number]

building1 = Building(4) # Construct a building with 4 floors
building1.occupy(0, 'Reception')
building1.occupy(1, 'ABC Corp')
building1.occupy(2, 'DEF Inc')
print( building1.get_floor_data(2) )

We could however use __getitem__ (and its counterpart __setitem__) to make the usage of the Building class 'nicer'.

class Building(object):
def __init__(self, floors):
self._floors = [None]*floors
def __setitem__(self, floor_number, data):
self._floors[floor_number] = data
def __getitem__(self, floor_number):
return self._floors[floor_number]

building1 = Building(4) # Construct a building with 4 floors
building1[0] = 'Reception'
building1[1] = 'ABC Corp'
building1[2] = 'DEF Inc'
print( building1[2] )

Whether you use __setitem__ like this really depends on how you plan to abstract your data - in this case we have decided to treat a building as a container of floors (and you could also implement an iterator for the Building, and maybe even the ability to slice - i.e. get more than one floor's data at a time - it depends on what you need.

What is magic about __len__()?

It might be helpful to think of __len__ as a method you can customize for any object. Part of the reason for the len function vs using .__len__() or .len() is that python was intended to be a language that is easy to learn. For a beginner programmer, understanding that you use the length function to get the length of a list seems very intuitive to me.

For example:

class MyObject:
def __len__(self):
return 100

a = MyObject()
assert len(a) == 100

So it's just a construct of all python objects that you can set how length is calculated. This example isn't useful, but perhaps if you had a Circle object, you might want length to be it's Circumference, ie.

 class Circle:
def __init__(self, radius):
self.radius = radius

def __len__(self):
return 3.14 * self.radius * 2

A benefit of having len as a function as well as a method is the ability to map-filter-reduce len onto arrays. It is very easy to write:

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

However, if you really think that .len() is an attractive way to present the length of an object, you could just add a method.

class MyObject:
def __len__(self):
return 10
def len(self):
return len(self)

What does the ```len``` keyword do and its definition

As explained in the official python documentation

Return the length (the number of items) of an object. The argument may be a sequence (such as a string, bytes, tuple, list, or range) or a collection (such as a dictionary, set, or frozen set).


Related Topics



Leave a reply



Submit