On Fri, May 15, 2015 at 6:59 PM, Marko Rauhamaa <ma...@pacujo.net> wrote: > However, in some respects, Python might be going overboard with its > dynamism; are all those dunder methods really needed?
Yes - at least, most of them. As regards operators, there are three options: either you have magic methods for all of them (Python style), or none of them (Java style, no operator overloading), or you hybridize and permit just a handful of them (and then you have to decide which). There's really no reason not to have them. The other dunder methods are a mixed bag; some are to allow you to customize object creation itself (a class's __new__ method could be considered equivalent to an instance-specific __call__ method on the type object), some let you pretend to be different types of number (__int__, __index__, __complex__), which allows you to duck-type integerness rather than having to subclass int and rely on magic; and others let you customize the behaviour of well-known functions, such as __len__ for len() and __repr__ for repr(). Without dunder methods for all of these, it would be difficult to make an object "play nicely" with the overall Python ecosystem. There are others, though, which are less crucial (__getstate__ and so on for pickle), but you can ignore them if you're not using those features. > Must "false" be defined so broadly? Different languages define true and false differently. REXX says that "1" is true and "0" is false, and anything else is an error. Pike says that the integer 0 is false and anything else is true; the philosophy is that a "thing" is true and the absence of any thing is false. Python says that an empty "thing" is false and a non-empty "thing" is true; if next(iter(x)) raises StopIteration, x is probably false, and vice versa. All three have their merits, all three have their consequences. One consequence of Python's model is that a __bool__ method is needed on any object that might be empty (unless it defines __len__, in which case that makes a fine fall-back); it's normal in Python code to distinguish between "if x:" and "if x is not None:", where the former sees if x has anything in it, but the latter sees if there x even exists. (More or less.) > Must a method lookup necessarily involve object creation? Actually, no. Conceptually, this method call: foo.bar(1, 2, 3) involves looking up 'foo' in the current namespace, looking up attribute 'bar' on it, treating the result as a function, and calling it with three integer objects as its arguments. And the language definition demands that this work even if the "foo.bar" part is broken out: def return_function(): return foo.bar def call_function(): return_function()(1, 2, 3) But a particular Python implementation is most welcome to notice the extremely common situation of method calls and optimize it. I'm not sure if PyPy does this, but I do remember reading about at least one Python that does; CPython has an optimization for the actual memory allocations involved, though I think it does actually construct some sort of object for each one; as long as the resulting behaviour is within spec, objects needn't be created just to be destroyed. Dynamism doesn't have to be implemented naively, just as long as the slow path is there if anyone needs it. ChrisA -- https://mail.python.org/mailman/listinfo/python-list