34

Just curious,

Is there any difference (advantages and disadvantages) between using len() or def __len__() when I build a class? And which is the best Python style?

   class foo(object):
      def __init__(self,obs=[])
         self.data = obs
         self.max = max(obs)
         self.min = min(obs)
         self.len = len(obs)

or

   class foo(object):
      def __init__(self,obs=[])
         self.data = obs
         self.max = max(obs)
         self.min = min(obs)
      def __len__(self):
         return len(self.data)
glglgl
  • 81,640
  • 11
  • 130
  • 202
Gianni Spear
  • 5,925
  • 15
  • 70
  • 115
  • 2
    How would the first one be equivalent to the second one? – Markus Unterwaditzer Feb 27 '13 at 14:05
  • 7
    Note that you should not use `[]` as a default value of a keyword parameter unless you know what you are doing. See ["Least Astonishment" in Python: The Mutable Default Argument](http://stackoverflow.com/q/1132941) – Martijn Pieters Feb 27 '13 at 14:06
  • 1
    In the first example, `self.len = len(obs)` assigns a data member `self.len` to the *initial* length of obs. `self.len` is not a function. If obs changes after initialization, `self.len` won't reflect that. – smci Aug 25 '18 at 02:43

2 Answers2

49

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
Martijn Pieters
  • 889,049
  • 245
  • 3,507
  • 2,997
7

There are several differences:

  1. Only the second approach will give you the familiar len(obj) syntax for foo. The first will require obj.len().
  2. If the length of self.data can change post-construction, only the second version will reflect the new length.
NPE
  • 438,426
  • 93
  • 887
  • 970