Mari terapkan ini dengan pembuatan tipe dinamis:
import copy
def namedgroup(typename, fieldnames):
def init(self, **kwargs):
attrs = {k: None for k in self._attrs_}
for k in kwargs:
if k in self._attrs_:
attrs[k] = kwargs[k]
else:
raise AttributeError('Invalid Field')
self.__dict__.update(attrs)
def getattribute(self, attr):
if attr.startswith("_") or attr in self._attrs_:
return object.__getattribute__(self, attr)
else:
raise AttributeError('Invalid Field')
def setattr(self, attr, value):
if attr in self._attrs_:
object.__setattr__(self, attr, value)
else:
raise AttributeError('Invalid Field')
def rep(self):
d = ["{}={}".format(v,self.__dict__[v]) for v in self._attrs_]
return self._typename_ + '(' + ', '.join(d) + ')'
def iterate(self):
for x in self._attrs_:
yield self.__dict__[x]
raise StopIteration()
def setitem(self, *args, **kwargs):
return self.__dict__.__setitem__(*args, **kwargs)
def getitem(self, *args, **kwargs):
return self.__dict__.__getitem__(*args, **kwargs)
attrs = {"__init__": init,
"__setattr__": setattr,
"__getattribute__": getattribute,
"_attrs_": copy.deepcopy(fieldnames),
"_typename_": str(typename),
"__str__": rep,
"__repr__": rep,
"__len__": lambda self: len(fieldnames),
"__iter__": iterate,
"__setitem__": setitem,
"__getitem__": getitem,
}
return type(typename, (object,), attrs)
Ini memeriksa atribut untuk melihat apakah mereka valid sebelum mengizinkan operasi dilanjutkan.
Jadi, apakah ini bisa dijadikan acar? Ya jika (dan hanya jika) Anda melakukan hal berikut:
>>> import pickle
>>> Point = namedgroup("Point", ["x", "y"])
>>> p = Point(x=100, y=200)
>>> p2 = pickle.loads(pickle.dumps(p))
>>> p2.x
100
>>> p2.y
200
>>> id(p) != id(p2)
True
Definisi tersebut harus ada dalam namespace Anda, dan harus ada cukup lama agar acar dapat menemukannya. Jadi jika Anda mendefinisikan ini sebagai paket Anda, itu harus berhasil.
Point = namedgroup("Point", ["x", "y"])
Pickle akan gagal jika Anda melakukan hal berikut, atau membuat definisi sementara (keluar dari ruang lingkup saat fungsi berakhir, katakanlah):
some_point = namedgroup("Point", ["x", "y"])
Dan ya, itu mempertahankan urutan bidang yang terdaftar dalam pembuatan tipe.