constructor classmethods

Ethan Furman ethan at stoneleaf.us
Thu Nov 3 10:45:28 EDT 2016


On 11/03/2016 01:50 AM, teppo.pera at gmail.com wrote:

> The guide is written in c++ in mind, yet the concepts stands for any
>  programming language really. Read it through and think about it. If
>  you come back to this topic and say: "yeah, but it's c++", then you
>  haven't understood it.

The ideas (loose coupling, easy testing) are certainly applicable in Python -- the specific methods talked about in that paper, however, are not.

To go back to the original example:

def __init__(self, ...):
     self.queue = Queue()

we have several different (easy!) ways to do dependency injection:

* inject a mock Queue into the module
* make queue a default parameter

If it's just testing, go with the first option:

import the_module_to_test
the_module_to_test.Queue = MockQueue

and away you go.

If the class in question has legitimate, non-testing, reasons to specify different Queues, then make it a default argument instead:

def __init__(self, ..., queue=None):
     if queue is None:
         queue = Queue()
     self.queue = queue

or, if it's just for testing but you don't want to hassle injecting a MockQueue into the module itself:

def __init__(self, ..., _queue=None):
     if _queue is None:
         _queue = Queue()
     self.queue = _queue

or, if the queue is only initialized (and not used) during __init__ (so you can replace it after construction with no worries):

class Example:
     def __init__(self, ...):
         self.queue = Queue()

ex = Example()
ex.queue = MockQueue()
# proceed with test

The thing each of those possibilities have in common is that the normal use-case of just creating the thing and moving on is the very simple:

my_obj = Example(...)

To sum up:  your concerns are valid, but using c++ (and many other language) idioms in Python does not make good Python code.

--
~Ethan~



More information about the Python-list mailing list