每当修改@property字段时,是否有一种简单的方法可以通知其他字段

问题描述 投票:0回答:1

我正在尝试定义一个集成了多种颜色空间表达的类。

即,

#'hsv', 'rgb'...such fields are different color space expression of one thing.

my_color = MyColor('#ffffff')
my_color.rgb   #(1.0, 1.0, 1.0)
my_color.rgb24 #(255, 255, 255)
my_color.hsv   #(0.0. 0.0, 1.0)

出于某种目的,我希望这个课程可以支持一些基本的数学运算,

my_color.hsv[2] -= 1.0

当然,当修改任何其他“绑定”字段时,所有字段都应该同步它们的值。

#after operation above.
my_color.rgb   #(0.0, 0.0, 0.0)
my_color.rgb24 #(0.0, 0.0, 0.0)
my_color.hsv   #(0.0, 0.0, 0.0)

这样做的最佳方式是什么。

我试过@property和@setter注释。

@property
def hsv(self):
    return self._hsv

@hsv.setter
def hsv(self, val):
    self._hsv = val
    _sync_change()  #update other fields by the new hsv value

我希望@setter可以帮助我根据新的'​​hsv'值更新其他字段。当我对my_color.hsv执行赋值操作时,它确实有效。

my_color.hsv = (0.5, 0.5, 0.5)
print(my_color.rgb, my_color.rgb24) #shows correct value.

但是,当我进行修改时,不是在元组上,而是在元组的元素上,事情就会出错。

my_color.hsv[2] -= 1.0
print(my_color.rgb, my_color.rgb24) #nothing changed.
print(my_color.hsv)  #nothing changed.

我想知道当我弄错了会发生什么,以及我可以用@setter方式做什么,或者是否有一种更好更自然的方式。

python class class-design color-conversion
1个回答
0
投票

您的属性返回一个列表对象,该列表对象基本上是独立的。就属性而言,您只读取该列表对象。

您的扩充任务声明:

my_color.hsv[2] -= 1.0

否则不设置该属性。它在列表中设置索引。以下大致相同:

_hsv_list = my_color.hsv
_hsv_list[2] = _hsv_list[2].__isub__(1.0)  # __isub__ is called to handle -=

那里没有my_color.hsv = _hsv_list,因此你的二传手永远不会被召唤。

所以诀窍是返回一个自定义对象,一个允许你拦截__setitem__和其他访问的对象:

from collections.abc import Sequence

class HSVValues(Sequence):
    _parent: MyColor

    def __init__(self, parent):
        self._parent = parent

    def __len__(self):
        return len(self._parent._hsv)

    def __getitem__(self, item):
        return self._parent._hsv[item]

    def __setitem__(self, item, value):
        self._parent._hsv[item] = value
        self._parent._sync_change()

并从您的财产返回:

@property
def hsv(self):
    return HSVValues(self)

所以现在my_color.hsv不返回_hsv值,而是返回上述类的实例。

使用该对象替换原始列表,_hsv_list[2] = _hsv_list[2].__isub__(1.0)将调用__setitem__,然后首先更新self._parent._hsv[2],然后在父类上调用_sync_change()方法以使其计算出所有其他值。

您可能希望_sync_changes接受更多有关更改内容的信息;如果它知道_hsv[2]改变了那可能使同步操作更有效率。

© www.soinside.com 2019 - 2024. All rights reserved.