आइए इसे गतिशील प्रकार के निर्माण के साथ लागू करें:
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)
यह देखने के लिए विशेषताओं की जांच करता है कि क्या ऑपरेशन जारी रखने की अनुमति देने से पहले वे वैध हैं।
तो क्या यह लाइलाज है? यदि आप (और केवल अगर) निम्नलिखित करते हैं:
>>> 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
परिभाषा आपके नामस्थान में होनी चाहिए, और इसे खोजने के लिए अचार में लंबे समय तक मौजूद रहना चाहिए। इसलिए यदि आप इसे अपने पैकेज में होना चाहते हैं, तो यह काम करना चाहिए।
Point = namedgroup("Point", ["x", "y"])
यदि आप निम्नलिखित करते हैं, तो अचार विफल हो जाएगा, या परिभाषा को अस्थायी बना देगा (कार्य समाप्त होने पर स्कोप से बाहर चला जाता है, कहते हैं):
some_point = namedgroup("Point", ["x", "y"])
और हाँ, यह प्रकार निर्माण में सूचीबद्ध फ़ील्ड के क्रम को संरक्षित करता है।