Pythonic替代dict风格的二传手?

时间:2014-04-06 22:43:51

标签: python coding-style setter getter getter-setter

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

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函数来获取密钥和值会更简单。但有更多的Pythonic方法来做这个重构吗?

1 个答案:

答案 0 :(得分:4)

您描述的不是属性的情况。属性用于允许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()

如果你想让这个类似dict的对象知道它的父对象是什么(例如,因为副作用应该发生在父对象上,那么将父对象作为参数传递给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)

关于getter / setter,你正在做的事情不是典型的getter / setter。不鼓励的是getSomeProp()setSomeProp(value)之类的东西,其中为每个属性设置了一个单独的方法。在您的示例中,您将描述不同的内容,这是一种用于设置键值对的通用获取/设置机制(可能对对象的行为有一些意义)。使用方法setPair(key, value)并不比使用名为doSomething(arg1, arg2)的方法更糟糕。这里有一个额外的参数,因此您的任务不适合obj.key = value的简单模式。如果您希望obj.prop[key] = value中的键/值到"知道"您还有一个额外的间接层。 obj;在obj.prop[key] = value之类的作业中,键和值是从obj中删除的一步,并且仅与prop直接互动。

您也可以使用John Smith Optional建议的简单方法来完成。无论您是想以这种方式执行,还是使用我所描述的自定义对象,都取决于您希望如何设置API。围绕自定义"数据保持"构建代码可以获得可读性优势。像我在这里概述的类,但它确实使实现更复杂。