考虑以下类定义
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)
答案 0 :(得分:20)
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'))
答案 1 :(得分:5)
我看到你的setter只记录一条消息,然后只是分配值 - 事实上,你接受的答案只是分配值。你是否正在使用这种模式,因为它是其他语言中的接受实践/常规智慧,也许是以“J”开头的名字?如果是这样,那么请了解Pythonic对这种设计的方法要简单得多:
class Of2010(object):
def __init__(self):
self.a = 1
self.b = 2
self.c = 3
没有do-nothing setter,没有中间函数调用只是为了赋值。 “你说的话? “公众接触成员变量?!!”好吧,实际上是。
从客户端代码的角度来看这些类。要使用您的类,客户端创建一个对象,然后使用:
分配属性“a”obj = Of2010()
obj.a = 42
值得注意的是,这与我上面发布的5-liner类完全相同。
为什么J语言鼓励更冗长的财产风格?在将来更改需求时保留类接口。如果在某个时间点,对象的某些其他值必须随着对a的任何更改而改变,那么您必须实现属性机制。遗憾的是,J语言将属性访问机制的性质暴露给客户端代码,因此在将来的某个时刻引入属性是一种侵入性重构任务,需要重建使用该类的所有客户端和它的“一个”属性。
在Python中,情况并非如此。访问对象的“a”属性是在调用者的运行时确定的。由于直接访问和属性访问都“看起来”相同,因此即使实际机制不同,Python类也会保留此接口。重要的是,就客户端代码而言,它是完全相同的。
所以在Java中,人们从这个类的开始(事实上,通过Accepted Practice,所有类)开始介绍这个属性的复杂性,因为它很可能是必要的。将来的某一天。使用Python,可以从实现可能工作的最简单的事情开始,也就是说,直接访问简单的成员变量,将复杂的方法留在将来实际需要额外的东西和价值的时间。由于那一天可能永远不会真正到来,所以这是将代码的第一个工作版本推出门的巨大进展。
答案 2 :(得分:2)
class...
def __setattr__(self, name, value):
print 'setting', name
self.__dict__[name] = value
就是这样。
答案 3 :(得分:1)
可能你正在寻找
__setattr__(self, name, value)
看看here