Python:多个属性,一个 setter/getter
Posted
技术标签:
【中文标题】Python:多个属性,一个 setter/getter【英文标题】:Python: multiple properties, one setter/getter 【发布时间】:2011-01-08 13:51:31 【问题描述】:考虑以下类定义
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)
【问题讨论】:
【参考方案1】:也许你正在寻找
__setattr__(self, name, value)
看看here
【讨论】:
【参考方案2】: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'))
【讨论】:
这是属性(fset=...),否则我会使用类似的东西。【参考方案3】:class...
def __setattr__(self, name, value):
print 'setting', name
self.__dict__[name] = value
就是这样。
【讨论】:
此建议已过时。根据docs.python.org/2/reference/…,“对于新型类,而不是访问实例字典,__setattr__
应该调用具有相同名称的基类方法,例如object.__setattr__(self, name, value)
。”请注意,OP 使用的是新式类。
@ChrisJohnson object.__setattr__(self, name, value)
中的对象是什么?内置对象?
是的,他们的意思是 object
内置类型。在现代 Python 中,这可能只是 super().__setattr__(name, value)
,如果 __setattr__
定义在不是 object
的超类中。
并且由于这些是已定义的属性,因此它们实际上需要实现__setattribute__
,而不是__setattr__
。 __setattribute__
总是被调用,但 __setattr__
只有在尚未为对象定义 attr 名称时才会被调用。【参考方案4】:
我看到您的设置者只是记录一条消息,然后简单地分配值 - 事实上,您接受的答案 只是 分配了值。您是否正在使用这种模式,因为它是其他语言中的公认实践/传统智慧,也许是一个名字以“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 类也会保留此接口。重要的是,就客户端代码而言,它是相同的。
因此,在 Java 中,从这个类(事实上,根据公认实践,所有类)一开始就引入了这种属性复杂性,因为它可能成为必要的未来的某一天。使用 Python,可以从实现可能工作的最简单的事情开始,即直接访问简单的成员变量,将复杂的方法留到将来实际需要额外的东西并且有价值的时候。由于那一天可能永远不会真正到来,因此将代码的第一个工作版本推出市场是一个巨大的飞跃。
【讨论】:
我希望在设置某个类的某些成员(实例)时发生一个动作。我希望对这些成员执行相同的操作(我的示例:打印成员的名称),而无需复制他们的设置器。这就是我需要二传手的原因。否则,正如您明智地指出的那样。我不会使用它们,因为它们在 python 中是不必要的 如果就像在每次调用时打印一个名称一样简单,为什么不将其编码到父级__init__() 中,每个实例都会调用它?以上是关于Python:多个属性,一个 setter/getter的主要内容,如果未能解决你的问题,请参考以下文章