If you are willing to use syntax like obj['happy'] = 14
then you could use __getitem__
and __setitem__
:
def __getitem__(self, key):
if key not in self.traits.keys():
raise KeyError
...
return traits[key]
def __setitem__(self, key, value):
if key not in self.traits.keys():
raise KeyError
...
traits[key] = value
If you really do want obj.traits['happy'] = 14
then you could define a subclass of dict
and make obj.traits
an instance of this subclass.
The subclass would then override __getitem__
and __setitem__
(see below).
PS. To subclass dict
, inherit from both collections.MutableMapping
, and dict
. Otherwise, dict.update
would not call the new __setitem__
.
import collections
class TraitsDict(collections.MutableMapping,dict):
def __getitem__(self,key):
return dict.__getitem__(self,key)
def __setitem__(self, key, value):
value = int(value)
if not 1 <= value <= 10:
raise ValueError('{v} not in range [1,10]'.format(v=value))
dict.__setitem__(self,key,value)
def __delitem__(self, key):
dict.__delitem__(self,key)
def __iter__(self):
return dict.__iter__(self)
def __len__(self):
return dict.__len__(self)
def __contains__(self, x):
return dict.__contains__(self,x)
class Person(object):
def __init__(self):
self.traits=TraitsDict({'happy': 0, 'worker': 0, 'honest': 0})
p=Person()
print(p.traits['happy'])
# 0
p.traits['happy']=1
print(p.traits['happy'])
# 1
p.traits['happy']=14
# ValueError: 14 not in range [1,10]
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…