16

考虑以下类定义

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

4 回答 4

21
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'))
于 2010-01-23T15:14:16.263 回答
7

我看到您的设置者只是记录一条消息,然后简单地分配值-实际上,您接受的答案只是分配了值。您是否正在使用这种模式,因为它是其他语言中的公认实践/传统智慧,也许是一个名字以“J”开头的语言?如果是这样,那么请了解这种相同设计的 Pythonic 方法要简单得多:

class Of2010(object):
    def __init__(self):
        self.a = 1
        self.b = 2
        self.c = 3

没有什么都不做的设置器,没有中间函数调用只是为了分配一个值。“你说的话?“成员变量公开曝光?!!” 嗯,实际上的。

从客户端代码的角度来看这些类。要使用您的类,客户端创建一个对象,然后使用以下方法分配属性“a”:

obj = Of2010()
obj.a = 42

值得注意的是,这与我在上面发布的 5-liner 类的代码完全相同。

为什么 J 语言鼓励更详细的属性样式?在未来需求发生变化时保留类接口。如果在某个时间点,对象的某些其他值必须随着对 a 的任何更改而更改,那么您必须实现属性机制。遗憾的是,J 语言将属性访问机制的本质暴露给客户端代码,因此在未来某个时间引入属性是一项侵入性重构任务,需要重建所有使用该类的客户端及其“a”属性。

在 Python 中,情况并非如此。对对象的“a”属性的访问是在运行时在调用者中确定的。由于直接访问和属性访问都“看起来”相同,因此即使实际机制不同,您的 Python 类也会保留此接口。重要的是,就客户端代码而言,它是相同的。

So in Java, one introduces this property complexity right from the inception of this class (and in fact, by Accepted Practice, of all classes), on the off-chance that it may become necessary some day in the future. With Python, one can start by implementing the Simplest Thing That Could Possibly Work, that is, direct access to simple member variables, leaving the complex approach for the time in the future that the extra stuff is actually required and of value. Since that day may never actually come, this is a huge jump forward in getting that first working version of your code out the door.

于 2010-01-23T16:00:52.317 回答
3

可能是你在寻找 __setattr__(self, name, value)

看看这里

于 2010-01-23T15:12:26.393 回答
1
class...
 def __setattr__(self, name, value):
  print 'setting', name
  self.__dict__[name] = value

就是这样。

于 2010-01-23T15:20:23.723 回答