Python的@property等价于处理中的类声明?

2024-04-19 19:24:28 发布

您现在位置:Python中文网/ 问答频道 /正文

在家放寒假的时候,我将尝试用处理编程语言(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方法来适当地解释所有这些,但是我似乎无法确定在处理中这样做的方法。你知道吗


Tags: self版本属性定义defnpline数学
1条回答
网友
1楼 · 发布于 2024-04-19 19:24:28

如果只使用常规的处理对象和语法,您几乎可以自动得到这个结果。你知道吗

例如,可以使用两个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类的用户通过setter更改端点,然后访问PVector实例。你知道吗

编辑:我将在这里回答您的其他问题。你知道吗

is public necessary?

这完全取决于您如何使用这个类,您希望其他人如何访问它,等等。您可以在the Processing reference中了解这一点,或者在google上搜索类似“java访问修饰符”的内容。或者你可以试着把它拿出来看看会发生什么。你知道吗

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.

我不太清楚你在问什么。在编写类时,您可以决定如何表示您的状态,以及如何让人们与该状态进行交互。你知道吗

例如,我上面的示例使用两个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值即可。你知道吗

相关问题 更多 >