Factory method for objects - best practice? Factory method for objects - best practice? python python

Factory method for objects - best practice?


First, most of the time you think you need something like this, you don't; it's a sign that you're trying to treat Python like Java, and the solution is to step back and ask why you need a factory.

Often, the simplest thing to do is to just have a constructor with defaulted/optional/keyword arguments. Even cases that you'd never write that way in Java—even cases where overloaded constructors would feel wrong in C++ or ObjC—may look perfectly natural in Python. For example, size = Size(bytes=20), or size = Size(20, Size.BYTES) look reasonable. For that matter, a Bytes(20) class that inherits from Size and adds absolutely nothing but an __init__ overload looks reasonable. And these are trivial to define:

def __init__(self, *, bits=None, bytes=None, kilobits=None, kilobytes=None):

Or:

BITS, BYTES, KILOBITS, KILOBYTES = 1, 8, 1024, 8192 # or object(), object(), object(), object()def __init__(self, count, unit=Size.BITS):

But, sometimes you do need factory functions. So, what do you do then? Well, there are two kinds of things that are often lumped together into "factories".

A @classmethod is the idiomatic way to do an "alternate constructor"—there are examples all over the stdlib—itertools.chain.from_iterable, datetime.datetime.fromordinal, etc.

A function is the idiomatic way to do an "I don't care what the actual class is" factory. Look at, e.g., the built-in open function. Do you know what it returns in 3.3? Do you care? Nope. That's why it's a function, not io.TextIOWrapper.open or whatever.

Your given example seems like a perfectly legitimate use case, and fits pretty clearly into the "alternate constructor" bin (if it doesn't fit into the "constructor with extra arguments" bin).