The main use case I use for this is to prevent small modules from spreading and to prevent namespace pollution when separate modules are not needed. If I extend an existing class, but this existing class should refer to another subclass that should always be associated with it. For example, I might have a utils.py module in which there are many helper classes that are not necessarily connected together, but I want to strengthen the connection for some of these helper classes. For example, when I implement https://stackoverflow.com/a/316947/
: utils.py :
import json, decimal class Helper1(object): pass class Helper2(object): pass # Here is the notorious JSONEncoder extension to serialize Decimals to JSON floats class DecimalJSONEncoder(json.JSONEncoder): class _repr_decimal(float): # Because float.__repr__ cannot be monkey patched def __init__(self, obj): self._obj = obj def __repr__(self): return '{:f}'.format(self._obj) def default(self, obj): # override JSONEncoder.default if isinstance(obj, decimal.Decimal): return self._repr_decimal(obj) # else super(self.__class__, self).default(obj) # could also have inherited from object and used return json.JSONEncoder.default(self, obj)
Then we can:
>>> from utils import DecimalJSONEncoder >>> import json, decimal >>> json.dumps({'key1': decimal.Decimal('1.12345678901234'), ... 'key2':'strKey2Value'}, cls=DecimalJSONEncoder) {"key2": "key2_value", "key_1": 1.12345678901234}
Of course, we could refuse to inherit json.JSONEnocder altogether and simply override default ():
:
import decimal, json class Helper1(object): pass def json_encoder_decimal(obj): class _repr_decimal(float): ... if isinstance(obj, decimal.Decimal): return _repr_decimal(obj) return json.JSONEncoder(obj) >>> json.dumps({'key1': decimal.Decimal('1.12345678901234')}, default=json_decimal_encoder) '{"key1": 1.12345678901234}'
But sometimes just for convention, you want utils consist of classes for extensibility.
Here is another use case: I want to use factory for modables in my OuterClass without having to call copy :
class OuterClass(object): class DTemplate(dict): def __init__(self): self.update({'key1': [1,2,3], 'key2': {'subkey': [4,5,6]}) def __init__(self): self.outerclass_dict = { 'outerkey1': self.DTemplate(), 'outerkey2': self.DTemplate()} obj = OuterClass() obj.outerclass_dict['outerkey1']['key2']['subkey'].append(4) assert obj.outerclass_dict['outerkey2']['key2']['subkey'] == [4,5,6]
I prefer this template over the @staticmethod decoder, which otherwise you would use for the factory function.