The Python standard library and PEP8

Steven D'Aprano steven at
Mon Apr 20 10:55:19 CEST 2009

On Mon, 20 Apr 2009 08:05:01 +0200, Emmanuel Surleau wrote:

> On Monday 20 April 2009 01:48:04 Steven D'Aprano wrote:
>> It also depends on whether you see the length of a data structure as a
>> property of the data, or the result of an operation ("counting") on the
>> data structure. We often fall into the trap of saying such things as
>> "the string HAS A length of 42" when what we really mean is "if you
>> count the elements of the string we find 42 of them". I don't believe
>> that the relationship between strings and length is a has-a
>> relationship. I believe it is a property requiring a function
>> (counting) to emerge, and therefore under OO principles, length should
>> *not* be an attribute and Java et al are guilty of misuse of OO in
>> making length an attribute.
> This didn't quite make sense. Methods are "abilities" an object has. Why
> shouldn't a string be able to compute its length?

Nothing. I'm not talking about methods, I'm talking about making length a 
property (or attribute if you prefer).

I must admit a mistake: Java does not treat the length of a string as an 
attribute, but uses a callable method, String.length(), so I withdraw my 
accusation of misuse of OO principles.

> As noted above, nothing would stop Fred from having the ability to
> "computeHeight()", though. I guess you could say that what I find silly
> is that String objects have a number of abilities, which: - are more
> complicated than retrieving their own length - most likely use len()
> internally anyway

Advantages of calling a length method:

- Consistency with other methods.

- Makes it easy to discover by introspection.

Disadvantages of calling a length method:

- In Python for built-in lists, tuples and strings, it requires at least 
one extra attribute lookup that the len() function doesn't need. (Java 
can avoid paying that cost at runtime by doing it at compile time -- this 
isn't available to Python.)

- It makes it more difficult to write functional code such as this:

map(len, [seq1, seq2, seq3])

where the various seq* are arbitrary sequences, not necessarily just 
strings. (Functional in the sense of functional-programming, not in the 
sense of "it works".)

- It makes it harder to intercept calls to len() for debugging. I can do 

def len(obj):
    print "called len with arg %r" % obj  # or log it somewhere
    return __builtins__.len(obj)

and have all the calls to len go through that, without even knowing what 
type of object is being called. 

But note that because len() in turn calls obj.__len__ (unless obj is a 
known built-in like str), you keep all the advantages of OO methods like 
sub-classing, without any of the disadvantages.

> And yet, when asked, it's not able to do something as basic as tell its
> length. This seems inconsistent to me.

Well, you can do this:

>>> s = "abc"
>>> s.__len__()

but if you do it in public, be prepared to have other Python programmers 
laugh at you.

It's just a stylistic difference, it's not a functional difference. Even 
if there is a genuine, objective advantage to one approach over the other 
(and I believe that advantage goes to len() as a function), it's quite 
small and it won't really make that big a difference.


More information about the Python-list mailing list