The Python standard library and PEP8
steven at REMOVE.THIS.cybersource.com.au
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
print "called len with arg %r" % obj # or log it somewhere
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"
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