4

I'm digging into Python 3.3 now and I wonder why some functions (for example, sorted(), reversed()) for managing collections/iterable are built-in but some are implemented as methods of collection objects? I can append item to list using method append(), but to get a length of it I should using built-in function len(). It seems inconsistent to me, but I think I just missing some point in new language.

artvolk
  • 9,448
  • 11
  • 56
  • 85
  • 1
    `sorted` takes any iterable as its first parameter. Contrast with `sort` which is a list method. – cdarke Jan 27 '14 at 21:56
  • I should read FAQ first: https://docs.python.org/3/faq/design.html#why-does-python-use-methods-for-some-functionality-e-g-list-index-but-functions-for-other-e-g-len-list :) – artvolk Oct 29 '14 at 14:59

1 Answers1

5

The short answer is that these decisions were made for human reasons rather than technical reasons.

The reasoning for len() versus obj.length() is explained by Guido van Rossum (Python's Benevolent Dictator For Life):

First of all, I chose len(x) over x.len() for HCI reasons (def __len__() came much later). There are two intertwined reasons actually, both HCI:

(a) For some operations, prefix notation just reads better than postfix — prefix (and infix!) operations have a long tradition in mathematics which likes notations where the visuals help the mathematician thinking about a problem. Compare the easy with which we rewrite a formula like x*(a+b) into x*a + x*b to the clumsiness of doing the same thing using a raw OO notation.

(b) When I read code that says len(x) I know that it is asking for the length of something. This tells me two things: the result is an integer, and the argument is some kind of container. To the contrary, when I read x.len(), I have to already know that x is some kind of container implementing an interface or inheriting from a class that has a standard len(). Witness the confusion we occasionally have when a class that is not implementing a mapping has a get() or keys() method, or something that isn’t a file has a write() method.

He also explains why sorted() and reversed() aren't methods:

Also note that many functions are defined in terms of informal interfaces; for example, reversed works on anything that supports random access to items and has a known length. In practice, implementing things like max, sum, map, any, in and others, as built-in functions and operators is actually less code than implementing them as methods for each and every type that needs to support them.

Simeon Visser
  • 118,920
  • 18
  • 185
  • 180
  • The last paragraph about `sorted()` and `reversed()` is a good point, but why they don't using something like mixins or even abstract methods for this? – artvolk Jan 27 '14 at 21:58
  • Just to clarify: I'm coming from C# where collections classes and interfacese are not built into language itself. – artvolk Jan 27 '14 at 22:00
  • 1
    @artvolk: it's a language design decision. Mixins and abstract methods work well in C# and Java but Python relies more on duck typing. If you want a new collection to behave in a certain way, you just add some methods and instances can then be used by various built-in functions. – Simeon Visser Jan 27 '14 at 22:06
  • At least, that was the case when these design decisions were made. Now that we have ABCs, `reverse()` and `__reversed__()` in fact are mixin methods of `MutableSequence` and `Sequence`. `sorted` still has no point of customization. Maybe because if the `key` parameter is set there's basically nothing that a container can contribute to the process. – Steve Jessop Jan 27 '14 at 22:52