"jonathan.beckett" <[EMAIL PROTECTED]> wrote: > I'm just finding it a bit weird that some of the built in functions are > static, rather than methods of objects (such as len() being used to > find the length of a list).
When it comes down to it, its a design decision, so neither right nor wrong in itself. You need to look a bit wider than just 'len' to understand it. There is the historical attribute: as I understand it, once upon a time, way back in the mists of time tuples didn't have methods at all, so you had to use a global function if you wanted to get the length of a tuple. That of course is no longer the case. However, ignoring for a moment that this may have been part of the reason why Python started in the direction of global helper functions, there are a lot of reasons why it turns out to have been a good decision. Consider 'sum' for a moment. The function needs to know how to iterate over a sequence, but the sequence itself doesn't need to provide any support apart from iteration to be supported by 'sum'. If 'sum' was a method then you would have to implement it separately in every summable object; implement it in a common base class to all iterables; provide a 'Summable' mixin class requiring every designer of an iterable to decide at the outset whether they want it to be summable; or provide an adaptor class which takes an iterator and returns a summable iterator (which just adds a needless extra layer of complexity over the global function we started with). 'min', 'max', 'sorted', 'zip' are other functions which similarly provide support to any kind of iterable without encumbering the iterable protocol itself. Next consider 'iter'. That's a global function which calls the __iter__ method, but it also has a fallback behaviour. Before Python had __iter__ iteration was define by calling __getitem__ with increasing index values, and if you don't have an __iter__ method the iter builtin will try the old protocol instead. So the global function has some more benefits: we can change the protocol it implements and continue to provide backward compatability, and we can have it do more than just calling the method which does the implementation. getattr is another example of a builtin which appears to do the job of a method (__getattribute__) but actually does a whole lot more with fallback and exception handling in the function. Converting an AttributeError exception to a default value would be particularly nasty to get right if we were depending on a direct call to a base class __getattribute__ which might be overridden in the implemented class. cmp is another good example: cmp(a,b) returns a.__cmp__(b), but if a doesn't have an __cmp__ method then it tries to return -b.__cmp__(a) (and has another fallback if even that fails). There is also an argument that Python uses __ to distinguish internal implementation details so that the internal methods are effectively kept out of the user's namespace. The ordinary user shouldn't need to worry about the presence of __ methods as they never need to call them directly. In fact for beginners probably __init__ and "if __name__=='__main__':" are the only things besides 'keep off the double underscores' that they need to know about them. So where does that leave 'len'? It is a function primarily for consistency with the general idea that you call a builtin (or a function imported from a support module) rather than calling a __ method directly. It does add some minimal functionality over calling __len__ directly, but not such that you'ld normally notice the difference. -- http://mail.python.org/mailman/listinfo/python-list