Using len() and def __len__(self): to build a class
Question:
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)
Answers:
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
There are several differences:
- Only the second approach will give you the familiar
len(obj)
syntax for foo
. The first will require obj.len()
.
- If the length of
self.data
can change post-construction, only the second version will reflect the new length.
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)
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
There are several differences:
- Only the second approach will give you the familiar
len(obj)
syntax forfoo
. The first will requireobj.len()
. - If the length of
self.data
can change post-construction, only the second version will reflect the new length.