Factory method for python object - best practice

This is a question regarding best practice of creating an instance of a class or type from different forms of the same data using python. Is it better to use a class method or is it better to use a separate function in general? Suppose I have a class used to describe the size of a document. (Note: This is just an example. I want to know how best to instantiate the NOT class, the best way to describe the size of the document.)

class Size(object): """ Utility object used to describe the size of a document. """ BYTE = 8 KILO = 1024 def __init__(self, bits): self._bits = bits @property def bits(self): return float(self._bits) @property def bytes(self): return self.bits / self.BYTE @property def kilobits(self): return self.bits / self.KILO @property def kilobytes(self): return self.bytes / self.KILO @property def megabits(self): return self.kilobits / self.KILO @property def megabytes(self): return self.kilobytes / self.KILO 

My __init__ method accepts the size value represented in bits (bits and only bits, and I want to save it that way), but lets say that I have the size value in bytes and I want to instantiate my class. Is it better to use a class method or is it better to use a separate function in general?

 class Size(object): """ Utility object used to describe the size of a document. """ BYTE = 8 KILO = 1024 @classmethod def from_bytes(cls, bytes): bits = bytes * cls.BYTE return cls(bits) 

OR

 def create_instance_from_bytes(bytes): bits = bytes * Size.BYTE return Size(bits) 

This may not seem like a problem, and maybe both examples are valid, but I think about it every time I need to implement something like this. For a long time, I preferred the class method approach because I like the organizational advantages of binding a class and factory method. In addition, using the class method retains the ability to instantiate any subclasses so that they are more oriented on objects. On the other hand, a friend once said: "When in doubt, do what the standard library does," and I have not yet found an example of this in the standard library.

Any feedback is greatly appreciated.

Greetings

+21
python coding-style decorator factory-method class-method
Feb 21 '13 at 0:21
source share
1 answer

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

Often the simplest thing is to simply create a constructor with default / optional / keyword arguments. Even cases that you will never write in Java, even cases where overloaded constructors will not feel right in C ++ or ObjC, may seem completely natural in Python. For example, size = Size(bytes=20) or size = Size(20, Size.BYTES) look reasonable. In this case, the Bytes(20) class, which inherits from Size and adds absolutely nothing, but the __init__ overload looks reasonable. And this is trivial:

 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 need factory functions. So what are you doing then? Well, there are two types of things that are often combined into "factories."

A @classmethod is an idiomatic way to execute an "alternative constructor" - there are examples for all stdlib- itertools.chain.from_iterable , datetime.datetime.fromordinal , etc.

A function is an idiomatic way of making a "I don't care what the actual class is" factory. Take a look, for example, at the built-in open function. Do you know what it returns in 3.3? You care? Nope. That is why it is a function, not io.TextIOWrapper.open or something else.

Your given example seems to be quite a legitimate precedent and fits very clearly into the bit of the alternative constructor (if it does not fit into the "constructor with additional arguments" bin).

+21
Feb 21 '13 at 0:28
source share



All Articles