Pythonic alternative to dict-style setter?



人们倾向于认为getters和setters不是Pythonic的,更喜欢使用@property。 我目前正在尝试扩展使用@property来支持字典的类的功能:

class OldMyClass(object):
    @property
    def foo(self):
       return self._foo
    @foo.setter
    def foo(self, value):
        self.side_effect(value)
        self._foo = value
class NewMyClass(object):
    @property
    def foo(self, key):  # Invalid Python
        return self._foo[key]
    @foo.setter
    def foo(self, key, value):  # Invalid Python
        self.side_effect(key, value)
        self._foo[key] = value

当然,我可以创建一些辅助类来处理这个问题,但似乎只是编写接受键和值的 setter/getter 函数会简单得多。但是有没有一种更 Python 的方式来进行这种重构呢?

你所描述的不是属性的情况。 属性用于允许obj(或者更确切地说,它的类)自定义obj.prop = value的行为。 如果你想自定义obj.prop[key] = value,那么你需要处理的不是obj而是obj.prop,这意味着你需要使obj.prop成为一个自定义类。 您在这里想要的是创建一个带有__setitem__的自定义类。

class Foo(object):
    def __init__(self):
        self._vals = {}
    def __setitem__(self, key, val):
        do_side_effect(key, val)
        self._vals[key] = val

然后在你的MyClass __init__,做self.foo = Foo()

如果你想让这个类似字典的对象知道它的父对象是什么(例如,因为副作用应该发生在父对象上,那么将父对象作为参数传递给 Foo:

class Foo(object):
    def __init__(self, parent):
        self.parent = parent
        self._vals = {}
    def __setitem__(self, key, val):
        parent.do_side_effect(key, val)
        self._vals[key] = val

然后在MyClass.__init__你做self.foo = Foo(self).

关于吸气手/二

传手,你正在做的不是典型的吸气手/二传手。 不鼓励的事情是像getSomeProp()setSomeProp(value)这样的事情,其中您获得/设置的每个属性都有一个单独的方法。 在您的示例中,您描述了一些不同的东西,这是一种用于设置键值对的通用 get/set 机制(可能对对象的行为具有某种意义)。 拥有setPair(key, value)的方法并不比拥有一种名为doSomething(arg1, arg2)的方法差。 在这里,您有一个额外的参数,因此您的任务不适合简单的obj.key = value模式。 如果您希望obj.prop[key] = value中的键/值"了解"obj,您还有一个额外的间接层;在像obj.prop[key] = value这样的赋值中,键和值与obj相距一步,并且仅与prop直接交互。

您也可以按照John Smith Optional的建议使用简单的方法进行操作。 是要以这种方式还是使用我描述的自定义对象,取决于您希望如何设置 API。 围绕自定义"数据保存"类构建代码(如我在此处概述的类)具有可读性优势,但它确实使实现更加复杂。

最新更新