【问题标题】:Can I add parameters to a python property to reduce code duplication?我可以向 python 属性添加参数以减少代码重复吗?
【发布时间】:2010-11-25 17:14:54
【问题描述】:

我有以下课程:


class Vector(object):
    def __init__(self, x=0, y=0, z=0):
        self.x = x
        self.y = y
        self.z = z

    def _getx(self):
        return self._x
    def _setx(self, value):
        self._x = float(value)
    x = property(_getx, _setx)

    def _gety(self):
        return self._y
    def _sety(self, value):
        self._y = float(value)
    y = property(_gety, _sety)

    def _getz(self):
        return self._z
    def _setz(self, value):
        self._z = float(value)
    z = property(_getz, _setz)

这三个 getter 和 setter 都是相同的,除了它们正在修改的对象属性 (x, y, z)。有没有办法可以写一个get和一个set,然后传递变量来修改,这样我就不会重复自己了?

【问题讨论】:

    标签: python


    【解决方案1】:

    当然,根据this doc 中清楚解释的概念制作自定义描述符:

    class JonProperty(object):
        def __init__(self, name):
            self.name = name
    
        def __get__(self, obj, objtype):
            return getattr(obj, self.name)
    
        def __set__(self, obj, val):
            setattr(obj, self.name, float(val))
    

    然后就使用它:

    class Vector(object):
        def __init__(self, x=0, y=0, z=0):
            self.x = x
            self.y = y
            self.z = z
        x = JonProperty('_x')
        y = JonProperty('_y')
        z = JonProperty('_z')
    

    【讨论】:

      【解决方案2】:

      为什么不直接写这个?

      class Vector(object):
          def __init__(self, x=0, y=0, z=0):
              self.x = x
              self.y = y
              self.z = z
      

      如果您的 getter 和 setter 在实践中是从 Java 之类的东西中继承而来,那么请不要编写它们。只需公开属性 x、y 和 z。如有必要,您可以稍后将它们更改为属性,并且与 Java(需要某种重新编译)不同,所有客户端代码仍然可以正常工作。

      关于 Python 中的 getter 和 setter 主题,据我所知,普遍的共识是“在需要它们之前不要编写它们”。仅当 setter 和 getter 真正为您的程序增加价值时才编写它们(比如保护内部数据结构,也许)。否则,将它们排除在外,并花时间进行实际高效的编码。

      【讨论】:

      • 最初我想要一种机制来保证 x、y 和 z 始终是浮点数,以防用户输入 int 或字符串。但是,我开始更多地考虑这个问题并同意你的看法。我将继续保持“我们都是成年人”的 Python 态度,并将其留给班级用户以确保存储浮点数。不过,我学到的关于定义装饰器的知识是值得的。
      【解决方案3】:

      未经测试,但这应该可以工作:

      def force_float(name):
          def get(self):
              return getattr(self, name)
          def set(self, x):
              setattr(self, name, float(x))
          return property(get, set)
      
      class Vector(object):
          x = force_float("_x")
          y = force_float("_y")
          # etc
      

      【讨论】:

      • 是的,它可以工作,除了你应该初始化 _x 和 _y。
      猜你喜欢
      • 1970-01-01
      • 2018-07-06
      • 1970-01-01
      • 2015-11-19
      • 2021-05-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-01-31
      相关资源
      最近更新 更多