【问题标题】:Python's @property equivalent in class declaration in Processing?处理中类声明中 Python 的 @property 等效项?
【发布时间】:2015-12-22 18:11:58
【问题描述】:

在寒假回家时,我将尝试使用 Processing 编程语言(Java 风格)制作一些很酷的东西。对于我的第一个项目,我想定义一个自定义 Line 类,以便更轻松地在线进行数学运算。在 python 中,它会是这样的:

import numpy as np

class Line():
    def __init__(self, x1, y1, x2, y2):
        self.x1, self.x2 = x1, x2
        self.y1, self.y2 = y1, y2

    @property
    def p1(self):
        return np.array([self.x1, self.y1])

    @property
    def p2(self):
        return np.array([self.x2, self.y2])

这样,如果 x1, ..., y2 改变,相应的点向量也会改变。显然这个例子效率有点低,但重点仍然存在。在javascript中,我知道Object.defineProperty(obj, prop, descriptor),但不清楚

  • 如何在处理中做到这一点
  • 这在哪里发挥作用。定义类时的等效操作是什么?

编辑:澄清为什么@property 特别有用:

假设我希望以两种方式表示线,这两种方式都将由 Line 对象存储:

  • 一,原版:两个点,p1 和 p2,每个点都由一个 x、y 坐标组成。
  • 两个带有两个点 u 和 v 的参数化版本,使得 p1 = u 和 p2 = u + v,线段上的任何点由 u + t * v 给出,其中 t 是 0 和1.

如果 p2 改变了,v 也会改变,反之亦然。更改 p1 将同时更改 u 和 v。就参数化版本而言,有些数学更容易做,而就香草版本而言,有些数学更容易做,所以我希望对任何属性所做的任何更改都正确更新其他属性,使 p1、p2 和 u、v 始终表示相同的行。

在 python 中,我可以修改属性的 setter 和 getter 方法以适当地解决所有这些问题,但我似乎无法确定在 Processing 中执行此操作的方法。

【问题讨论】:

  • 您打算使用哪种处理方式? (Java/JavaScript/Python/等?)?
  • Java(我认为是原始的?)。最初我只是打算做 Python,但我一直坚持寻找 x 的 python 版本来完成任务 y。

标签: java python class processing processing.js


【解决方案1】:

如果您只使用常规的处理对象和语法,您几乎可以自动获得。

例如,您可以使用两个 PVector 实例来定义端点。

class Line{
   PVector p1;
   PVector p2;

   public Line(float x1, float y1, float x2, float y2){
      p1 = new PVector(x1, y1);
      p2 = new PVector(x2, y2);
   }
}

然后,如果您想更改其中一个端点,您可以直接访问 PVector 实例:

Line myLine = new Line(0, 10, 25, 100);
println(myLine.p1.x + ", " myLine.p1.y);
myLine.p1.x = 750;
println(myLine.p1.x + ", " myLine.p1.y);

您还可以获得PVector class 中已经定义的所有数学内容。

您可以更好地“保护”您的 PVector 变量,方法是使它们成为最终变量,或者只允许您的 Line 类的用户通过设置器更改端点,然后访问 PVector 实例。

编辑:我会尝试在这里回答您的其他问题。

有必要公开吗?

这完全取决于你如何使用这个类,你希望其他人如何访问它等等。你可以在the Processing reference 中了解这一点,或者只是谷歌诸如“java 访问修饰符”之类的东西。或者你可以试着把它拿出来看看会发生什么。

如果我同时想要行的原始定义 (x1, y1, x2, y2) 和参数化 (u1, u2, v1, v2, s.t. x1 = u1 和 x2 = u1 + v1 等) 版本怎么办?在这种情况下,重要的是,如果 x2 更新,v1 也应该更新。

我不确定你在这里问什么。在编写课程时,您可以决定如何表示您的状态以及如何让人们与该状态进行交互

例如,我上面的示例使用两个PVector 实例来表示线条,它允许人们直接与它们交互以修改该线条。但我可以添加一个函数,让他们将一条线定义为一个点、一个角度和一个距离。我只需要确保我计算出第二点,这样我就可以存储我的状态。像这样的:

class Line{
   PVector p1;
   PVector p2;

   public Line(float x1, float y1, float x2, float y2){
      p1 = new PVector(x1, y1);
      p2 = new PVector(x2, y2);
   }

   public Line(PVector origin, float angle, float distance){
      p1 = origin;
      p2 = new PVector(origin.x + cos(angle)*distance, origin.y + sin(angle)*distance);
   }
}

请注意,第二个构造函数允许用户以完全不同的方式指定一行,但我仍然将我的状态存储为两个 PVector 实例。如果您以后需要它们,您可以存储 angledistance 值,并且您可以拥有允许用户修改它们的设置器 - 您只需相应地更新您的 PVector 值。

【讨论】:

  • 非常感谢!不过有几个问题:public 有必要吗?我看到的一些例子没有使用它。此外,如果我同时想要线的原始定义 (x1, y1, x2, y2) 和参数化 (u1, u2, v1, v2, s.t. x1 = u1 和 x2 = u1 + v1 等) 版本怎么办?在这种情况下,重要的是,如果 x2 更新,v1 也应该更新。
猜你喜欢
  • 2014-06-10
  • 1970-01-01
  • 2013-03-09
  • 2013-09-12
  • 2011-01-10
  • 2012-09-28
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多