python - 如何在Python中将类似属性的对象与字典值关联

标签 python dictionary properties setter

我正在使用字典对象来保存类中的实例值。我喜欢使用字典,因为我经常想同时设置或获取一堆值,并且很容易传递列表或字典来完成此操作。例如,要获取多个实例值,我只需传递一个[键列表]并返回一个{这些键的字典:值}。据我所知,如果可能的话,为每个键使用单独的属性来实现这一点需要跳过很多代码圈。

无论如何,我正在寻找这样的东西:

class SomeClass(object):
    def __init__(self):
        self._desc = {
            'hair': 'brown'
            'eyes': 'blue'
            'height': 1.55
        }

到目前为止,这一切都非常简单,但有些值需要特殊的“设置”条件。我的第一次尝试是这样的:

class SomeClass(object):
    def __init__(self):
        self._haircolor = 'blonde'
        self._eyecolor = 'green'
        self._desc = {
            'haircolor': self.haircolor
            'eyecolor': self.eyecolor
            'height': 1.55
        }

    @property
    self.haircolor(self):
        return self._haircolor

    @haircolor.setter
    self.haircolor(self, color):
        if color.lower() in ['blonde', 'brunette', 'brown', 'black', 'auburn', 'red']:
            self._haircolor = color
        else: raise ValueError()

    # Same type of property construct for eyecolor

这不起作用。 self._desc['haircolor'] 将初始化为 blonde,但它与属性构造或 self._haircolor 属性没有动态联系。我尝试将其替换为

class SomeClass(object):
    def __init__(self):
        self._haircolor = 'blonde'
        self._eyecolor = 'green'
        self._desc = {
            'haircolor': property(self.get_haircolor, self.set_haircolor)
            'eyecolor': property(self.get_eyecolor, self.set_eyecolor)
            'height': 1.55
        }

    self.get_haircolor(self):
        return self._haircolor

    self.set_haircolor(self, color):
        if color.lower() in ['blonde', 'brunette', 'brown', 'black', 'auburn', 'red']:
            self._haircolor = color
        else: raise ValueError()

但这以不同的方式失败了。

print self._desc['haircolor'] 

将为属性对象返回一个str,并且

self._desc['haircolor'] = 'brunette'

销毁了属性对象并用字符串替换它。

我研究了一些类似的问题,例如 this onethis one

然而,这两种情况都是在字典级别上运行的。问题是,当我定义自定义 dict 类时,我需要了解很多关于 dict 的信息,因为我需要预测键名称并在 setitem (第一个示例)或 dict 级别中切换它们属性对象(第二个示例)。理想情况下,我希望将 setter 与值对象本身关联起来,这样字典就不需要知道键可以引用的值有什么特殊之处。

最佳答案

Python 对象已经将属性存储在字典中,那么这里使用另一个字典有什么意义呢?只需以通常的方式存储属性(在有意义的地方使用属性),并在需要时动态构建 desc 字典即可。

class SomeClass(object):

    HAIRCOLORS = set(['blonde', 'brunette', 'brown', 'black', 'auburn', 'red'])
    EYECOLORS = set(['green', 'blue', 'brown', 'gray'])

    def __init__(self, haircolor="blond", eyecolor="green"):
        self.haircolor = haircolor
        self.eyecolor = eyecolor
        self.height = 1.55 # you didn't mention any validation here

    @property
    def haircolor(self):
        return self._haircolor

    @haircolor.setter
    def haircolor(self, color):
        color = color.lower()
        if color not in self.HAICOLORS:
            raise ValueError("'%s' is not a valid hair color" % color)
        self._haircolor = color

    # same thing for eyecolor

    @property
    def desc(self):
        return dict(
           haircolor=self.haircolor, 
           eyecolor=self.eyecolor, 
           height=self.height)

如果这是一个重复出现的模式,您最终可以编写自己的描述符:

class ChoiceDescriptor(object):
    def __init__(self, key, choices):
        self.key = key
        self.storage = "_%s" % key
        self.choices = set(choices)

    def __get__(self, instance, cls=None):
        if instance is None:
            return self
        return getattr(instance, self.storage)


    def __set__(self, instance, value):
        value = value.lower()
        if value not in self.choices:
            raise ValueError(
                "'%s' is not a valid value for '%s'" % (value, self.key))
        setattr(instance, self.storage, value)


class SomeClass(object):
    haircolor = ChoiceDescriptor("haircolor", 
        ['blonde', 'brunette', 'brown', 'black', 'auburn', 'red'])
    eyecolor = ChoiceDescriptor("eyecolor", 
        ['green', 'blue', 'brown', 'gray'])

关于python - 如何在Python中将类似属性的对象与字典值关联,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20561002/

相关文章:

python - 如何在colab中安装coco数据集?

python - 在 python 中没有 for 循环的情况下重复函数几次

javascript - .map 在更新状态后没有重新渲染

python - 在将 python 集与自定义对象相交时选择要保留的元素

Tomcat + 管理属性文件

javascript - 我怎样才能让 JSLint 停止提示 Ember.js ".property()"s?

Python 线程循环方法不会继续代码

python - 在文件中保存并读取 `\r` - Python 3

python - Python 中列表和字典的映射

java - 如何查找操作系统位类型