正确使用字典值的getter/setter

jb.*_*jb. 12 python getter-setter

我对Python很陌生,所以如果这里的任何内容都很糟糕,请指出.

我有一个这个字典的对象:

traits = {'happy': 0, 'worker': 0, 'honest': 0}
Run Code Online (Sandbox Code Playgroud)

每个特征的值应该是1-10范围内的int,并且不应该允许添加新特征.我想要getter/setter所以我可以确保保留这些约束.以下是我现在制作getter和setter的方法:

def getTrait(self, key):
    if key not in self.traits.keys():
        raise KeyError

    return traits[key]

def setTrait(self, key, value):
    if key not in self.traits.keys():
        raise KeyError

    value = int(value)

    if value < 1 or value > 10:
        raise ValueError

    traits[key] = value
Run Code Online (Sandbox Code Playgroud)

我读了这个网站有关的property()方法.但我没有看到一种简单的方法来利用它来获取/设置字典中的值.有一个更好的方法吗?理想情况下,我希望使用这个对象obj.traits['happy'] = 14,这将调用我的setter方法并抛出一个ValueError,因为14超过10.

unu*_*tbu 11

如果你愿意使用像那样的语法,obj['happy'] = 14你可以使用__getitem____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
Run Code Online (Sandbox Code Playgroud)

如果你真的想要,obj.traits['happy'] = 14那么你可以定义一个子类dict并创建obj.traits这个子类的实例.然后,子类会覆盖__getitem____setitem__(见下文).

PS.要dict继承,继承collections.MutableMappingdict.否则,dict.update不会打电话给新的__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]
Run Code Online (Sandbox Code Playgroud)

  • 你也可以写`if not 1 <value <10`而不是`或`条件. (2认同)