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的主要内容,如果未能解决你的问题,请参考以下文章

Python:多个属性,一个 setter/getter

VUE核心学习笔记

VUE核心学习笔记

一个类应该有多个属性或一个属性作为具有许多键的字典,Python3

如何保存属性也是对象并且在多个级别上的python对象?

Python面向对象-18.类属性