JARGON ALERT: this post contains jargon, jargon, and more jargon; you may want to skip directly to the last three paragraphs. Otherwise enjoy some tasty jargon! Mmmm.
I was surprised that almost none of the Python code I’ve written makes use of the Inversion of Control techniques of Dependency Injection or Service Locator. I’ve used the Service Locator design pattern extensively in the C# and C++ code I’ve written over the last decade, and I’ve made extensive use of C++ templates to achieve at compile time what the Dependency Injection design pattern achieves at runtime.
Given the extensive period and common frequency that I have used those two IoC design patterns I was taken aback that not only was not using those patterns in my Python code, but I hadn’t even noticed!
After a brief knee-jerk impulse to add an item to my TODO list to fix this oversight, I took some time for considered thought and came to the conclusion that this was generally fine. C++ and C# are both statically typed languages that purposefully make it difficult to access attributes that have been explicitly made accessible, where Python is dynamically typed everything is accessible whether the developer wants it to be or not.
For example in Python ‘private’ members are still accessible through a portable naming convention, so ‘private’ is really a mechanism for communicating “no guarantees are made that using this will work in the future) rather than an access prevention mechanism. This means anything can be overridden, including imports of other modules, as imported modules are just attributes of the importing module and can be modified the same as an object’s attributes. Additionally, the classes an object inherits from can be modified at runtime (i.e. Python supports mixins), so the Curiously Recurring Template Pattern is not needed. Finally, the signature of functions and methods can changed without needing to change all of the locations calling them. While both C++ and C# (4.0+) do allow adding additional default parameters, neither allows removing parameters. In Python removing parameters is possible in many cases.
There are some exceptions to this, such as when ‘__slots__’ is used to reduce the memory footprint the objects of a particular class, and there are certainly cases where the use of the design patterns are part of the primary usage scenario for a type, but there are the exceptions rather than the general case.
The key difference is that there are far fewer ‘things’ that will result in needing to refactor simple Python code then there are for simple C++ or C# code. As a result, there is less need to utilize more complicated designs in Python to achieve testability or extensibility (aka future proofing).
Less time spent on designing for testability and extensibility means more time for producing functionality.
Thus: ++productivity == Python