从Python类中提取数据

时间:2015-08-30 10:38:59

标签: python class python-2.7

我编写了一个程序来计算和激活冥王星的轨道,并开始使用类重写它,因为这似乎是一种将更多行星引入模拟的合理方法。即有一个定义物理学的类,然后输入特定的行星数据以获得轨道数据。

    class Planet(object):
        m_sun = 1.989*(10**30)
        G = 6.67*(10**-11)
        dt = 1
        coords = []
        def __init__(self, x, y, vx, vy, m):
            self.x = x
            self.y = y
            self.vx = vx
            self.vy = vy
            self.m = m


        def genData(self):
            while self.dt < 100000000:
                r = ((self.x)**2 + (self.y)**2)**0.5
                a = ((self.G*self.m_sun)/r**2)
                ax = -a*((self.x)/r)
                ay = -a*((self.y)/r)
                self.vx = self.vx + ax*self.dt
                self.vy = self.vy + ay*self.dt
                self.x = self.x + self.vx*self.dt
                self.y = self.y + self.vy*self.dt
                coord = (self.x, self.y)
                print coord
                self.coords.append(coord)
                self.dt = self.dt + 1000

pluto = Planet(4495978707000, 0, 0, 4670, 1.305*(10**22))
pluto.genData()

我确定它并不完美,但似乎有效(这是我自己建立的第一堂课)。我的问题是如何将“coords”中的数据提取到我可以在课堂外工作的列表中。

我想为每个星球生成数据,然后使用这些数据在Pygame中创建动画。例如,冥王星,地球,土星等的(x,y)坐标列表。就目前而言,它会生成数据,但似乎无法从课外访问。

我希望我的问题有道理。

谢谢!

4 个答案:

答案 0 :(得分:4)

您的问题已得到解答,但我发现您应该找到一些有助于改进您的计划的信息。从技术上讲,这个信息属于评论(因为你在你的问题中没有真正询问过这个问题),但它不适合。 :)

  1. 冥王星的轨道相对于黄道很倾向,所以如果你想在太阳系中将它与其他几颗行星一起绘制,你需要在3D中工作才能准确。但我想这对你的申请来说并不是什么大问题。

  2. 与冥王星相比,地球的轨道很小,因此您可能需要实施缩放以在一个动画上看到它们。

  3. 使用Standard gravitational parameter而不是使用单独的G和质量值,您可以在计算中获得更高的准确性。

  4. 您计算速度和位置的算法称为Euler integration。它相当于用多边形近似轨道曲线。它有效,但不是很准确。因此,您需要使时间差非常小,否则轨道不会非常逼真,甚至可能不是闭合曲线。即使这并没有多大帮助,因为错误是累积的,所以最终计算出的轨道与现实几乎没有相似之处。

  5. 没有任何数值积分技术是完美的(除了非常简单的函数),但是一个更流行的集成技术系列更准确(因此工作正常,时间步长更大)是Runge-Kutta methods。您可以使用Runge-Kutta方法找到许多示例轨道计算代码;大多数代码示例使用称为RK4的变体。

    但是,强烈敦促您尝试Leapfrog集成。编写Leapfrog的同步形式非常容易,并且它比Runge-Kutta有一个主要的好处,因为它是辛的,它(大致)意味着它节省了能量,所以错误赢得了&#39;从轨道到轨道累积。

答案 1 :(得分:3)

你试过pluto.coords吗?

您可以使用后跟dot后跟成员名称的实例(即属性访问权限)从外部访问类的成员。这与调用genData()方法时一样。

顺便说一句,您可以使用指数表示法定义常量:

m_sun = 1.989e+30
G = 6.67e-11

pluto = Planet(4495978707000, 0, 0, 4670, 1.305e+22)

更具可读性(重要性)并为您的班级定义保存一些计算(更少/不重要)。

答案 2 :(得分:3)

而不是将值存储在self.coordsyield the values

    def genData(self):
        while self.dt < 100000000:
            ...  
            self.x = self.x + self.vx*self.dt
            self.y = self.y + self.vy*self.dt
            coord = (self.x, self.y)
            yield coord
            self.dt = self.dt + 1000

pluto = Planet(4495978707000, 0, 0, 4670, 1.305*(10**22))

for coord in pluto.genData():
    print(coord)

请注意,这会使genData成为generator function

要获取坐标列表,您可以在循环中累积值:

coords = []
for coord in pluto.genData():
    coords.append(coord)

或使用coords = list(pluto.genData())

顺便说一下,将代码计算与代码打印分开通常是一个很好的策略。这样你可以多次调用代码计算,或者将它包含在一系列计算中,而不必总是发出打印语句。

  

我想为每个星球生成数据,然后使用这些数据在Pygame中创建动画。

听起来您不需要累积数据。您可以绘制每个行星的当前点,而无需了解行星的坐标历史。在这种情况下,使用生成器函数将更具内存效率,因为它们允许您为每个行星生成下一个坐标,而不必首先将所有坐标存储在列表中:

# In Python2 
import itertools as IT
for coords in IT.izip(*[planet.genData() for planet in [pluto, neptune, uranus, ...]]):
    # plot coords

# In Python3
for coords in zip(*[planet.genData() for planet in [pluto, neptune, uranus, ...]]):
    # plot coords

答案 3 :(得分:2)

实际上这很容易,只有pluto.coords

pluto = Planet(4495978707000, 0, 0, 4670, 1.305*(10**22))
pluto.genData()
print pluto.coords