python - 如何识别属性的属性何时被设置?

标签 python properties attributes

我有一个具有多个属性的可变对象(我们称之为 mutable)。该对象本身是 Foo 类中的一个属性。 Foo 是用户定义的,而 mutable 不是,因此不能更改。

每当有人试图在 mutable 中设置属性时,我都需要进行计算。我面临的问题是,使用 mutable 的属性仅在设置了 mutable 本身而不是其属性时才有效。我已经设法解决了这个问题,但使用的东西似乎比合理的 Python 代码更像是 hack。

class Mutable(object):  # Example class.

    def __init__(self):
        self.attr0 = 0
        self.attr1 = 1

    def __repr__(self):
        return str(self.__dict__)[1:-1]


class Foo(object):

    def __init__(self):
        self._mutable = Mutable()

    @property
    def mutable(self):
        print('mutable was read')
        return self._mutable

    @mutable.setter
    def mutable(self, attr_value_pair):
        attribute, value = attr_value_pair
        setattr(self._mutable, attribute, value)
        print('mutable.' + attribute, 'was set to', value)


bar = Foo()
print(bar.mutable)           # 'mutable was read'
bar.mutable = ('attr0', 5)   # 'mutable.attr0 was set to 5'
bar.mutable = ('attr1', 10)  # 'mutable.attr1 was set to 10'
print(bar.mutable)           # 'mutable was read'

# This is what I want to do but it only calls the getter.
bar.mutable.attr0 = 0        # 'mutable was read'
bar.mutable.attr1 = 1        # 'mutable was read'

有什么方法可以识别 mutable 中的属性何时以更 Pythonic 的方式设置?

编辑: 澄清一下:Foo 需要知道 mutable 何时更改,因为 Foo 具有依赖于可变Mutable 可以被继承。

最佳答案

最简单干净的解决方案是子类化 mutable - 但我认为这不是一个选项。

最简单的“quick&dirty”解决方案是使用 monkeypatch mutable - 但这实际上是最后的解决方案,从长远来看是在寻找麻烦。

因此,如果您不能将 mutable 子类化,也不能控制它的实例化,并且不想对其进行 monkeypatch,那么您只能使用 proxy 模式。

编辑:哦,是的,因为它是 Foo 需要得到关于 self._mutable 更改的通知,你必须将它与观察者模式结合起来(这里是非常有限的形式):

class Mutable(object):  # Example class.

    def __init__(self):
        self.attr0 = 0
        self.attr1 = 1

    def __repr__(self):
        return str(self.__dict__)[1:-1]



class MutableProxy(object):
    def __init__(self, mutable, owner):
        self._mutable = mutable
        self._owner = owner

    @property
    def attr0(self):
        return self._mutable.attr0

    @attr0.setter
    def attr0(self, value):
        self._mutable.attr0 = value 
        self._owner.notify("set", "attr0", value)


    @property
    def attr1(self):
        return self._mutable.attr1

    @attr1.setter
    def attr1(self, value):
        self._mutable.attr1 = value 
        self._owner.notify("attr1", value)

    def __repr__(self):
        return "<MutableProxy for {}>".format(repr(self._mutable))

class Foo(object):
    def __init__(self):
        self.mutable = Mutable()

    @property
    def mutable(self):
        #print('mutable was read')
        return self._mutable

    @mutable.setter
    def mutable(self, value):
        self._mutable = MutableProxy(value, self)

    def notify(self, attrname, value):
        print('self._mutable.{} was set to {}'.format(attrname, value))

注意:我没有在 MutableProxy.__init__ 中添加任何类型检查,这取决于你真正的 mutable 实际上是什么你可能想要确保你至少得到一些东西兼容...

NB2:我在 ProxyMutable 上使用了显式属性,因为它使事情更清晰,但您可能想使用 __getattr__/__setattr__ Hook (至少对于您不需要控制访问的 mutable 属性)。

NB3:我们现在在 FooMutableProxy 之间有一个循环引用。 Python normalluy 知道如何摆脱循环引用,但如果它碰巧仍然是您的具体用例的问题,您可能希望将 MutableProxy._owner 设置为 weak reference相反。

现在困扰我的问题是:为什么要公开 mutable ?完全隐藏它并仅通过 Foo 方法或属性提供对其属性的访问将使代码更简单(并且更容易推理并且不太可能产生意外副作用)。

关于python - 如何识别属性的属性何时被设置?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41330968/

相关文章:

python - 使用 OpenCV 和 ROS 时卡住黑色图像和轨迹栏

Python:如何将剩余的列表元素添加到列表中,类似于解压?

arrays - Jenkins Groovy 扩展属性数组

ios - 覆盖的 NSManagedObject getter 无法识别

java - 即使项目是一个 jar,指定从类路径读取的路径的最佳方法是什么

从另一台服务器下载时,HTML5 下载属性不起作用,即使 Access-Control-Allow-Origin 设置为全部 (*)

.net - 限制自定义属性的属性类型

python - 在caffe中使用分类时出错

python - 为什么 re.sub ('.*?' , '-' , 'abc' ) 返回 '-a-b-c-' 而不是 '-------' ?

opengl - Cocoa 和 OpenGL,如何使用数组设置 GLSL 顶点属性?