Learning Python - Mark Lutz [401]
* * *
Note
In fact, __del__ can be tricky to use for even more subtle reasons. Exceptions raised within it, for example, simply print a warning message to sys.stderr (the standard error stream) rather than triggering an exception event, because of the unpredictable context under which it is run by the garbage collector. In addition, cyclic (a.k.a. circular) references among objects may prevent garbage collection from happening when you expect it to; an optional cycle detector, enabled by default, can automatically collect such objects eventually, but only if they do not have __del__ methods. Since this is relatively obscure, we’ll ignore further details here; see Python’s standard manuals’ coverage of both __del__ and the gc garbage collector module for more information.
* * *
* * *
[68] In the current C implementation of Python, you also don’t need to close file objects held by the instance in destructors because they are automatically closed when reclaimed. However, as mentioned in Chapter 9, it’s better to explicitly call file close methods because auto-close-on-reclaim is a feature of the implementation, not of the language itself (this behavior can vary under Jython, for instance).
Chapter Summary
That’s as many overloading examples as we have space for here. Most of the other operator overloading methods work similarly to the ones we’ve explored, and all are just hooks for intercepting built-in type operations; some overloading methods, for example, have unique argument lists or return values. We’ll see a few others in action later in the book:
Chapter 33 uses the __enter__ and __exit__ with statement context manager methods.
Chapter 37 uses the __get__ and __set__ class descriptor fetch/set methods.
Chapter 39 uses the __new__ object creation method in the context of metaclasses.
In addition, some of the methods we’ve studied here, such as __call__ and __str__, will be employed by later examples in this book. For complete coverage, though, I’ll defer to other documentation sources—see Python’s standard language manual or reference books for details on additional overloading methods.
In the next chapter, we leave the realm of class mechanics behind to explore common design patterns—the ways that classes are commonly used and combined to optimize code reuse. Before you read on, though, take a moment to work though the chapter quiz below to review the concepts we’ve covered.
Test Your Knowledge: Quiz
What two operator overloading methods can you use to support iteration in your classes?
What two operator overloading methods handle printing, and in what contexts?
How can you intercept slice operations in a class?
How can you catch in-place addition in a class?
When should you provide operator overloading?
Test Your Knowledge: Answers
Classes can support iteration by defining (or inheriting) __getitem__ or __iter__. In all iteration contexts, Python tries to use __iter__ (which returns an object that supports the iteration protocol with a __next__ method) first: if no __iter__ is found by inheritance search, Python falls back on the __getitem__ indexing method (which is called repeatedly, with successively higher indexes).
The __str__ and __repr__ methods implement object print displays. The former is called by the print and str built-in functions; the latter is called by print and str if there is no __str__, and always by the repr built-in, interactive echoes, and nested appearances. That is, __repr__ is used everywhere, except by print and