【问题标题】:Class(dict): change key value on change of other key valueClass(dict):改变其他键值时改变键值
【发布时间】:2020-04-06 06:32:14
【问题描述】:

我有一个班级Color,如下图。我的问题是:初始化该类的实例后,某些键值的更改不再影响其他键值(请参见下面的示例)。 我怎样才能实现这种行为?

class Color(dict):

    def __init__(self, **args):

        try:
            self['name'] = args['name']
        except:
            self['name'] = 'unnamed_color'


        try:
            h = args['hex'].replace('#', '')
            rgb = tuple(int(h[i:i+2], 16) for i in (0, 2, 4))
            self['r'] = rgb[0]
            self['g'] = rgb[1]
            self['b'] = rgb[2]
            self['a'] = 1
        except:

            try:
                self['r'] = min(max(int(args['r']), 0), 255)
            except:
                self['r'] = 0
            try:
                self['g'] = min(max(int(args['g']), 0), 255)
            except:
                self['g'] = 0
            try:
                self['b'] = min(max(int(args['b']), 0), 255)
            except:
                self['b'] = 0
            try:
                self['a'] = min(max(int(args['a']), 0), 1)
            except:
                self['a'] = 0


        self['rgba'] = (self['r'],self['g'],self['b'],self['a'])
        self['rgb'] = (self['r'],self['g'],self['b'])
        self['hex'] = '#%02x%02x%02x' % self['rgb']


    def __getattr__(self, item):
        return self[item]


    def __str__(self):
        return self['name']

示例:

purple = Color(hex='#00ff00')
print(purple.rgba)    # returns (0, 255, 0, 1)
purple.r = 24
print(purple.rgb)     # still returns (0, 255, 0) but (12, 255, 0) expected

【问题讨论】:

  • 你真的不应该来自dict..!
  • 我为什么不应该呢?还有什么更好的方法?
  • @maxischl 很好的一个原因 - 因为Color 不是dict。你为什么要开始?这比class Color: 有什么优势?
  • 因为它出现了。我很高兴有更好的解决方案。无论如何,我经常使用 Class(dict),而颜色版本只是整个问题的一种形式;)

标签: python class dictionary


【解决方案1】:

您不应该从这样的类的 dict 派生(因为它不是真的,好吧,dictlike)。相反,听起来您想将 propertys 用于各种格式的 getter 和 setter。

有一个嵌入的doctest,所以如果你把它放到一个文件中并运行python -m doctest -v somefile.py,你可以看到Python正在尝试。

def clamp(v, a, b):
    return min(max(v, a), b)


class Color:
    """
    >>> c = Color(hex="#ff33ff")
    >>> c.r
    255
    >>> c.a = 0.5
    >>> c.rgba
    (255, 51, 255, 0.5)
    >>> purple = Color(hex='#00ff00')
    >>> purple.rgba
    (0, 255, 0, 1)
    >>> purple.r = 24
    >>> purple.rgb
    (24, 255, 0)
    """

    def __init__(self, name="unnamed color", hex=None, r=0, g=0, b=0, a=1):
        self.name = name
        self._r = self._g = self._b = self._a = 0
        self.r = r
        self.g = g
        self.b = b
        self.a = a
        if hex:
            self.hex = hex

    @property
    def r(self):
        return self._r

    @r.setter
    def r(self, value):
        self._r = clamp(value, 0, 255)

    @property
    def g(self):
        return self._g

    @g.setter
    def g(self, value):
        self._g = clamp(value, 0, 255)

    @property
    def b(self):
        return self._b

    @b.setter
    def b(self, value):
        self._b = clamp(value, 0, 255)

    @property
    def a(self):
        return self._a

    @a.setter
    def a(self, value):
        self._a = clamp(value, 0, 1)

    @property
    def hex(self):
        return "#%02x%02x%02x" % self.rgb

    @hex.setter
    def hex(self, value):
        h = str(value).replace("#", "")
        r, g, b = tuple(int(h[i : i + 2], 16) for i in (0, 2, 4))
        self.r = r
        self.g = g
        self.b = b
        self.a = 1

    @property
    def rgba(self):
        return (self.r, self.g, self.b, self.a)

    @property
    def rgb(self):
        return (self.r, self.g, self.b)

【讨论】:

  • 或者见鬼,忘了财产。只是普通班。并不是说这不是一个好的解决方案。
  • @juanpa.arrivillaga OP 的原版具有钳制 R/G/B/A 并在输入上解析十六进制字符串的行为;这只能通过属性实现。
  • 到目前为止我还没有听说过这些属性,我会读一下!是的:对我来说,有选择地在输入上设置一些值很重要
  • @maxischl 好吧,这里的属性是为了让您可以引入属性之间的动态相互关系。但是你总是可以让这些东西成为方法,只需使用.hex()
  • @juanpa.arrivillaga 那么最好将它们命名为.get_hex().set_hex() 等...此时您最好还是使用property。跨度>
猜你喜欢
  • 1970-01-01
  • 2018-12-03
  • 2021-03-20
  • 2023-03-31
  • 2019-01-07
  • 2020-01-18
  • 2019-07-20
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多