Python 的@属性 等同于 Processing 中的 class 声明?

Python's @property equivalent in class declaration in Processing?

在寒假回家期间,我将尝试使用 Processing 编程语言(Java 风格)制作一些很酷的东西。对于我的第一个项目,我想定义一个自定义 Line class 以使在线计算更容易。在 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 对象存储:

如果 p2 改变,v 也会改变,反之亦然。更改 p1 将更改 u 和 v。一些数学在参数化版本方面更容易完成,而一些在普通版本方面更容易完成,所以我希望对任何属性所做的任何更改都正确更新其他属性,使 p1、p2 和 u、v 始终代表相同的行。

在 python 中,我可以修改 属性 的 setter 和 getter 方法来适当地解释所有这些,但我似乎无法确定在处理中执行此操作的一种方法。

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

例如,您可以使用两个 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 中已定义的所有数学内容。

您可以更好地 "protect" 您的 PVector 变量,方法是将它们设为最终变量或仅允许 Line class 的用户通过设置器更改端点,然后访问PVector 个实例。

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

is public necessary?

这完全取决于您如何使用此 class、您希望其他人如何访问它等。您可以在 the Processing reference 中了解这一点,或者只是 google 类似于 "java access modifiers"。或者你可以试着把它拿出来,看看会发生什么。

what if I want both the vanilla definition of a line (x1, y1, x2, y2) and the parameterized (u1, u2, v1, v2, s.t. x1 = u1 and x2 = u1 + v1, etc) versions simultaneously? In this case, and importantly, if x2 is updated, so should v1 be updated.

我不太确定你在这里问什么。当你写下你的 class 时,你可以决定 你如何代表你的状态 以及 你如何让人们与该状态互动

例如,我上面的示例使用两个 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 值。