Package: rsdict
rsdictrsdict is arestrictedandresetabledictionary,
a subclass ofdict(inherits from built-in dictionary).>>>fromrsdictimportrsdict>>>d={"foo":0,"bar":"baz"}>>>rd=rsdict(d)>>>rdrsdict({'foo':0,'bar':'baz'},frozen=False,fixkey=True,fixtype=True,cast=False)# fixkey=True: key restriction>>>rd["newkey"]=1AttributeError# fixtype=True: type restriction>>>rd["foo"]="str.value"TypeError>>>rd["foo"]=999>>>rd==dFalse# reset values to initial>>>rd.reset()>>>rd==dTrueInstallationpipinstallrsdictFeaturesType-restrict(able): If activated, every type of value is fixed to its initial type.Key-restrict(able): If activated, cannot add or delete keys.Resettable: to initial value(s).Argumentsrsdict(items, frozen=False, fixkey=True, fixtype=True, cast=False)items (dict): Initial items (data).
Built-in dictionary only. kwargs are not supported.frozen (bool, optional): If True,
the instance will be frozen (immutable).fixkey (bool, optional): If True,
cannot add or delete keys.fixtype (bool, optional): If True,
cannot change type of keys.cast (bool, optional): If False,
cast to initial type (if possible).
If True, allow only the same type of initial value.Subclasses# rsdict(frozen=True) as defaultfromrsdictimportrsdict_frozenasrsdict# rsdict(fixkey=False, fixtype=False) as defaultfromrsdictimportrsdict_unfixasrsdict# rsdict(fixkey=True, fixtype=False) as defaultfromrsdictimportrsdict_fixkeyasrsdict# rsdict(fixkey=False, fixtype=True) as defaultfromrsdictimportrsdict_fixtypeasrsdictAdditional methodsset(key, value): Alias of__setitem__.to_dict() -> dict: Convert to dict instance.reset(key: Optional[Any]) -> None: Reset value to the initial value.
If key is None, reset all values.is_changed(key: Optional[Any]) -> bool: If True,
the values are changed from initial.
If key is not None, check the key only.get_initial(key: Optional[Any]) -> dict | Any: Return initial value(s).
If key is None, Return dict of all initial values.ExamplesCreate (Initialize)>>>fromrsdictimportrsdict>>>d=dict(...name="John",...enable=True,...count=0,...)>>>rd=rsdict(d)>>>rdrsdict({'name':'John','enable':True,'count':0},frozen=False,fixkey=True,fixtype=False)>>>type(rd)isdictFalse>>>isinstance(rd,dict)True>>>rd.frozenFalseGetSame asdict.>>>rd["count"]==d["count"]True>>>rd["xyz"]KeyError>>>rd.get("count")==d.get("count")True>>>rd.get("xyz")NoneSet>>>rd["enable"]=False>>>rd.set("enable",False)# If frozen, always raise an exception.>>>rd_frozen=rsdict(d,frozen=True)>>>rd_frozen["count"]=2AttributeError# If fixtype and not cast, different-type value raise an exception.>>>rd["count"]="2"TypeError# If fixtype and cast, cast value to initial type.>>>rd_cast=rsdict(d,cast=True)>>>rd_cast["count"]="2">>>rd_cast["count"]2>>>rd_cast["count"]="abc"ValueError# If not fixtype, anything can be set.>>>rd_typefree=rsdict(d,fixtype=False)>>>rd_typefree["count"]="2">>>rd_typefree["count"]'2'# If fixkey, setting with a new key raises an exception.>>>rd["location"]=9AttributeError# If not fixkey, a new key can be set.>>>rd_keyfree=rsdict(d,fixkey=False)>>>rd_keyfree["location"]=9>>>rd_keyfree["location"]9Delete# If frozen or fixkey, deleting key raises an exception.>>>delrd["count"]AttributeError# Else, delete both current and initial values.>>>rd_keyfree=rsdict(dict(a=1,b=2,c=3),fixkey=False)>>>delrd_keyfree["b"]>>>rd_keyfree.keys()dict_keys(['a','c'])>>>rd_keyfree.get_initial().keys()dict_keys(['a','c'])Reset# Check whether the values are changed from initial.>>>rd.is_changed()False# (Change some values.)>>>rd["enable"]=False>>>rd["count"]=5>>>rd.is_changed()True# Reset with a key.>>>rd.reset("count")>>>rd["count"]0>>>rd.is_changed()True# Reset all values.>>>rd.reset()>>>rd.is_changed()FalseCopy# Create a new rsdict with different optional arguments.# If reset, copy initial values only.>>>rd["name"]="Mike">>>rd2=rd.copy(reset=True)>>>rd2==rd.get_initial()True# If frozen and not reset, copy current values as new initial values.>>>rd3=rd.copy(frozen=True)>>>rd3rsdict({'name':'Mike','enable':True,'count':0},frozen=True,fixkey=True,fixtype=False,cast=False)>>>rd3==rdTrue>>>rd3.get_initial()==rd.get_initial()FalseCompare>>>rd1=rsdict({"key1":10,"key2":"abc"})>>>rd2=rsdict({"key1":20,"key2":"abc"})# Change current value.>>>rd2["key1"]=10# Current values are equal.>>>rd1==rd2True# Initial values are not equal.>>>rd1.get_initial()==rd2.get_initial()False# If compare with dict, use current values.>>>d2=rd2.to_dict()>>>rd2==d2Union(Python3.9 or later)>>>rd=rsdict({"key1":10,"key2":"abc"},fixkey=False)>>>d={"key2":20,"key3":False}# Return: dict>>>rd|d{'key1':10,'key2':20,'key3':False}>>>d|rd{'key2':'abc','key3':False,'key1':10}>>>rd|=d>>>rdrsdict({'key1':10,'key2':20,'key3':False},frozen=False,fixkey=False,fixtype=True,cast=False)# Add initial values of new keys only.>>>rd.get_initial(){'key1':10,'key2':'abc','key3':False}NoteExpected types of value:int,float,str,bool,None,list,dict,tuple,pathlib.PathSome types (e.g.numpy.ndarray) cannot be cast.Tested in Python3.5, 3.6, 3.7, 3.8, 3.9, 3.10.Only initial items are deepcopied.>>>d=dict(a=[1])>>>rd=rsdict(d)>>>rd["a"].append(2)>>>rdrsdict({'a':[1,2]},frozen=False,fixkey=True,fixtype=True,cast=False)>>>d{'a':[1,2]}>>>rd.get_initial(){'a':[1]}Performancersdict is slower thandictdue to its additional checking.Changelog->CHANGELOG.md