diff -r 5f3ac68f34f2 Doc/faq/design.rst --- a/Doc/faq/design.rst Mon Dec 26 18:52:46 2016 +0900 +++ b/Doc/faq/design.rst Mon Dec 26 20:59:50 2016 +0900 @@ -210,24 +210,49 @@ objects using the ``for`` statement. Fo Why does Python use methods for some functionality (e.g. list.index()) but functions for other (e.g. len(list))? ---------------------------------------------------------------------------------------------------------------- -The major reason is history. Functions were used for those operations that were -generic for a group of types and which were intended to work even for objects -that didn't have methods at all (e.g. tuples). It is also convenient to have a -function that can readily be applied to an amorphous collection of objects when -you use the functional features of Python (``map()``, ``zip()`` et al). +Guido says: -In fact, implementing ``len()``, ``max()``, ``min()`` as a built-in function is -actually less code than implementing them as methods for each type. One can -quibble about individual cases but it's a part of Python, and it's too late to -make such fundamental changes now. The functions have to remain to avoid massive -code breakage. + There are two bits of "Python rationale" that I'd like to explain first. + + 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. + + Saying the same thing in another way, I see 'len' as a built-in + *operation*. I'd hate to lose that. I can't say for sure whether you + meant that or not, but 'def len(self): ...' certainly sounds like you + want to demote it to an ordinary method. I'm strongly -1 on that. + + The second bit of Python rationale I promised to explain is the reason + why I chose special methods to look __special__ and not merely + special. I was anticipating lots of operations that classes might want + to override, some standard (e.g. __add__ or __getitem__), some not so + standard (e.g. pickle's __reduce__ for a long time had no support in C + code at all). I didn't want these special operations to use ordinary + method names, because then pre-existing classes, or classes written by + users without an encyclopedic memory for all the special methods, + would be liable to accidentally define operations they didn't mean to + implement, with possibly disastrous consequences. Ivan Krstić + explained this more concise in his message, which arrived after I'd + written all this up. -.. XXX talk about protocols? - -.. note:: - - For string operations, Python has moved from external functions (the - ``string`` module) to methods. However, ``len()`` is still a function. +https://mail.python.org/pipermail/python-3000/2006-November/004643.html Why is join() a string method instead of a list or tuple method?