人们倾向于认为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。 围绕自定义"数据保存"类构建代码(如我在此处概述的类)具有可读性优势,但它确实使实现更加复杂。