扩展了kjfletch的想法
# This is my humble contribution, extending the idea to serialize
# data from and to tuples, comparison operations and allowing functions
# as default values.
def Struct(*args, **kwargs):
FUNCTIONS = (types.BuiltinFunctionType, types.BuiltinMethodType, \
types.FunctionType, types.MethodType)
def init(self, *iargs, **ikwargs):
"""Asume that unamed args are placed in the same order than
astuple() yields (currently alphabetic order)
"""
kw = list(self.__slots__)
# set the unnamed args
for i in range(len(iargs)):
k = kw.pop(0)
setattr(self, k, iargs[i])
# set the named args
for k, v in ikwargs.items():
setattr(self, k, v)
kw.remove(k)
# set default values
for k in kw:
v = kwargs[k]
if isinstance(v, FUNCTIONS):
v = v()
setattr(self, k, v)
def astuple(self):
return tuple([getattr(self, k) for k in self.__slots__])
def __str__(self):
data = ['{}={}'.format(k, getattr(self, k)) for k in self.__slots__]
return '<{}: {}>'.format(self.__class__.__name__, ', '.join(data))
def __repr__(self):
return str(self)
def __eq__(self, other):
return self.astuple() == other.astuple()
name = kwargs.pop("__name__", "MyStruct")
slots = list(args)
slots.extend(kwargs.keys())
# set non-specific default values to None
kwargs.update(dict((k, None) for k in args))
return type(name, (object,), {
'__init__': init,
'__slots__': tuple(slots),
'astuple': astuple,
'__str__': __str__,
'__repr__': __repr__,
'__eq__': __eq__,
})
Event = Struct('user', 'cmd', \
'arg1', 'arg2', \
date=time.time, \
__name__='Event')
aa = Event('pepe', 77)
print(aa)
raw = aa.astuple()
bb = Event(*raw)
print(bb)
if aa == bb:
print('Are equals')
cc = Event(cmd='foo')
print(cc)
输出:
<Event: user=pepe, cmd=77, arg1=None, arg2=None, date=1550051398.3651814>
<Event: user=pepe, cmd=77, arg1=None, arg2=None, date=1550051398.3651814>
Are equals
<Event: user=None, cmd=foo, arg1=None, arg2=None, date=1550051403.7938335>