人们倾向于认为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方法来做这个重构吗?
答案 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。围绕自定义"数据保持"构建代码可以获得可读性优势。像我在这里概述的类,但它确实使实现更复杂。