Python:多个属性,一个设置器/获取器
考虑以下的类定义
class of2010(object):
def __init__(self):
self._a = 1
self._b = 2
self._c = 3
def set_a(self,value):
print('setting a...')
self._a = value
def set_b(self,value):
print('setting b...')
self._b = value
def set_c(self,value):
print('setting c...')
self._c = value
a = property(fset=self.set_a)
b = property(fset=self.set_b)
c = property(fset=self.set_c)
注意到 set_[a|b|c]()
这几个方法做的事情是一样的。有没有办法定义一个:
def set_magic(self,value):
print('setting <???>...')
self._??? = value
只定义一次,然后可以用在a、b、c上,像这样
a = property(fset=self.set_magic)
b = property(fset=self.set_magic)
c = property(fset=self.set_magic)
4 个回答
也许你在找的是 __setattr__(self, name, value)
你可以在 这里 看看
我注意到你的设置方法只是记录一条消息,然后简单地赋值——实际上,你接受的答案只是赋值。你这样做是因为这是某种语言中被广泛接受的做法吗?也许那种语言的名字是以“J”开头的?如果是这样的话,请了解在Python中,这种设计的更简单的做法是:
class Of2010(object):
def __init__(self):
self.a = 1
self.b = 2
self.c = 3
没有无所作为的设置方法,也没有为了赋值而进行的中间函数调用。“什么?!”你会说。“公开暴露成员变量?!!”其实,是的。
从客户端代码的角度来看这些类。要使用你的类,客户端需要创建一个对象,然后用以下方式赋值属性“a”:
obj = Of2010()
obj.a = 42
令人惊讶的是,这和我上面发布的五行代码是完全一样的。
为什么J语言鼓励使用更冗长的属性风格呢?是为了在未来需求变化时保持类的接口。如果在某个时刻,对象的其他值必须与“a”的变化一起改变,那么你就必须实现属性机制。可悲的是,J语言将属性访问机制的本质暴露给客户端代码,因此在未来引入一个属性将变成一个侵入性的重构任务,这需要重建所有使用该类及其“a”属性的客户端。
而在Python中,情况并非如此。对对象“a”属性的访问是在调用时决定的。由于直接访问和属性访问看起来是一样的,你的Python类在接口上保持一致,尽管实际机制不同。重要的是,从客户端代码的角度来看,它们是相同的。
所以在Java中,从这个类一开始就引入了这种属性复杂性(实际上,根据被接受的做法,所有类都是如此),以防将来某一天可能需要。而在Python中,可以先实现最简单的可行方案,也就是直接访问简单的成员变量,复杂的做法可以留到未来真正需要的时候再去实现。因为那一天可能永远不会到来,这在让你的代码尽快发布第一个可用版本上是一个巨大的进步。
这个代码块是用来展示一些编程内容的,具体的内容在这里没有给出。通常情况下,代码块会包含一些示例代码或者特定的编程指令,帮助人们理解如何实现某个功能。
如果你看到这样的代码块,通常意味着这里有一些重要的代码需要你去学习或者参考。记得仔细查看这些代码,它们可能会对你理解整个问题有很大帮助。
def attrsetter(attr):
def set_any(self, value):
setattr(self, attr, value)
return set_any
a = property(fset=attrsetter('_a'))
b = property(fset=attrsetter('_b'))
c = property(fset=attrsetter('_c'))