I've an object that looks like this, and users have been populating the attributes post-initialization, e.g.
class ObjectThingy:
def __init__(self):
self.att1 = set() # set(tuple)
self.att2 = {} # dict(str:str)
attribute1 = [('foo', 'bar'), ('soap', 'bar'), ('gastro', 'bar')]
attribute2 = {'hello': 'world', 'foo': 'bar'}
ot = ObjectThingy()
ot.att1 = attribute1
ot.att2 = attribute2
And now I'm trying to write an object loader without changing the number of variables in __init__ (maybe optional *args and **kwargs are okay though). I came up with a staticmethod that returns the an instantiation of the class:
import json
attribute1 = [('foo', 'bar'), ('soap', 'bar'), ('gastro', 'bar')]
attribute2 = {'hello': 'world', 'foo': 'bar'}
with open('object.json', 'w') as fout:
_json = {'att1': attribute1, 'att2': attribute2}
json.dump(_json, fout)
class ObjectThingy:
def __init__(self):
self.att1 = set() # set(tuple)
self.att2 = {} # dict(str:str)
@staticmethod
def load(jsonfile):
with open(jsonfile) as fin:
_json = json.load(fin)
att1 = set(map(tuple, _json['att1']))
att2 = _json['att2']
ot = ObjectThingy()
ot.att1.update(att1)
for k,v in att2.items():
ot.att2[k] = v
return ot
It kind of works but seems sort of off when I'm trying to just populate the object attributes when loading instead of initializing them. And I try another pattern where I minimize my loading function and offload the operations to checks using kwargs during initialization:
class ObjectThingy:
def __init__(self, **kwargs):
if 'att1' in kwargs and all(type(t) == tuple for t in kwargs['att1']):
self.att1 = set(map(tuple, kwargs['att1']))
else:
self.att1 = set() # set(tuple)
if 'att2' in kwargs and isinstance(kwargs['att2'], dict):
self.att2 = kwargs['att2']
else:
self.att2 = set() # set(tuple)
@staticmethod
def load(jsonfile):
with open(jsonfile) as fin:
_json = json.load(fin)
att1 = set(map(tuple, _json['att1']))
att2 = _json['att2']
return ObjectThingy(att1=att1, att2=att2)
ot3 = ObjectThingy.load('object.json')
print(ot3.att1)
print(ot3.att2)
Are there specific use-cases for which the previous/latter solution is preferred?
Are there other idiomatic patterns that we can use for similar object loading functions (pickling is not possible in my task)?
Is there any other possible way to load the object with/without staticmethod?
classmethodon SO, one dating back to '13. Is your question genuine? \$\endgroup\$att1andatt2should be constructor params. Your own factory function violates the class integrity when you doot.att1.update(att1)andot.att2[k] = v. ->def __init__(self, att1=None, att2=None): self.att1 = att1 or set(); self.att2 = att2 or dict(). By providing defaults you don't run into conflicts with existing code. \$\endgroup\$ot = ObjectThingy(); ot.att1 = attribute1; ot.att2 = attribute2. So probably it would be an good idea to provide accessors foratt1andatt2. \$\endgroup\$