Description
It's very simple to write straightforward imperative code with Python. You can easily define classes and functions, and write behavior inside them. However, pure imperative design means that you'll likely end up writing the same patterns of code over and over - whether it's requests.get() or LOGGER = getLogger(__name__). By taking advantage of some of the more advanced features of the Python language, like descriptors, overridden magic methods, and creative uses of inheritance, we can make our code smaller and more expressive. Proper abstractions will also make it easier to test your code thoroughly and effectively - because you're not reimplementing behavior unnecessarily, you can properly test the one place you do implement it, and rely on it from then on. And, it becomes much easier to add features later on that rely on existing behavior - you just need to describe them in terms of the things you've already implemented.