3

I wrote a program in C that uses structs to model the motion of planets going around the Sun. I want to write that same program in Python. The planets and Sun are treated as particles.

In C I wrote a struct for the data of any particle. In the 2D arrays, the rows are the x,y,z components and the columns are the old,current,new iterations. The acceleration of each particle doesn't change so it is an array of x,y,z components.

struct type_particle {
    double mass;
    double acceleration[3];
    double position[3][3];
    double velocity[3][3];
};

I used this struct variable to access data about specific particles. Each element in the array is a specific particle where N=9. For example, particle[0] is the Sun.

static struct type_particle particle[N];

I define the initial x-position of the Sun by

particle[0].position[0][0] = -0.002893107099833329;   

I want to do the same thing in Python using classes. I am just using the Sun and one planet so N=2. So far I have this.

class type_particle:
    particle = [N]
    def __init__(self, position):
        self.position = [],[]

I am not sure if I can define the class variable "particle" as a list. Is this on the right track to creating something that gives the same results as the struct and struct variable I used earlier? I read that classes can be used like structs but I do not understand how. My goal is to use a class to access data for a particular particle. Any help is appreciated.

  • You can, I don't get `self.position = [], []`? if you want a list of points, you can define a point `class` too. – Iharob Al Asimi Jan 21 '15 at 23:05
  • possible duplicate of [C-like structures in Python](http://stackoverflow.com/questions/35988/c-like-structures-in-python) – nbro Jan 21 '15 at 23:05
  • Right now, `particle` is defined as a list that contains the value of `N`, which means it's a list with one element in it. – Makoto Jan 21 '15 at 23:05
  • Yes, a class is like a struct with methods. But your array of structs is not part of the struct in C--why would you make it part of the class in Python? It should be a list of particle objects. The particle objects should just have the same members your struct does. – Lee Daniel Crocker Jan 21 '15 at 23:10

3 Answers3

3

What you need is a Python class. Since your use-case is quite simple, you can use a namedtuple which essentially creates a boilerplate class for you:

from collections import namedtuple

Particle = namedtuple('Particle', ['mass', 'acceleration', 'position', 'velocity'])

Then,

>>> sun_mass = 1.989e30
>>> sun_acceleration = [1, 2, 3]
>>> sun_position = [4, 5, 6]
>>> sun_velocity = [7, 8, 9]
>>> sun = Particle(sun_mass, sun_acceleration, sun_position, sun_velocity)
>>> sun
Particle(mass=1.989e+30, acceleration=[1, 2, 3], position=[4, 5, 6], velocity=[7, 8, 9])

Inspired by iharob's answer, you can also have a Vector namedtuple:

Vector = namedtuple('Vector', ['x', 'y', 'z'])

Even if you were to create your own class for Particle because you want to easily to some checks etc. before initialising it, you should still use a namedtuple for Vector as it is very simple. But, be mindful that namedtuples are immutable so once initialised you cannot change its attributes. For mass, that is fine because the mass doesn't change. But if you wanted to change the attributes on the Vector then you have to use a list instead, as shown in the first example.

s16h
  • 4,647
  • 1
  • 21
  • 33
  • I don't see the benefit in using this, what is it? – Iharob Al Asimi Jan 21 '15 at 23:23
  • If all is needed is a simple class with some attributes, then it's simpler to write and read; I feel it's more pythonic (although you may disagree). It may not be suitable if the OP requires to do different checks etc. when instantiating an object. But, since OP was using a struct, I assumed all OP needs is a container. – s16h Jan 21 '15 at 23:38
  • 1
    @iharob as for the benefit, namedtuples use less memory because their properties are not stored in a normal dict. It's essentially the same as your answer, but with `__slots__` and some other batteries included. – kalhartt Jan 22 '15 at 00:15
1

You have two options for this problem. The first is to use a class;

struct type_particle {
    double mass;
    double acceleration[3];
    double position[3][3];
    double velocity[3][3];
};

becomes

class TypeParticle:
    def __init__(self): #pass any kind of init variable you know as an argument
        self.mass = None
        self.acceleration = []
        self.position = []
        self.velocity = []

However, you should - maybe - look into dictionaries (the single most useful data object in Python - I think). However, this only makes sense if the number of particles is small, for a (large) list of dictionaries is, as was commented on, not something you want. In this case, this would become

type_particle = {
    'mass' = 0.,
    'acceleration' = [],
    'position' = [],
    'velocity' = []
}

you could then access it with e.g.

type_particle['acceleration']

Some explanation: Python duck-types and dynamically allocates memory. Therefore you do need neither to set the types, nor the exact size of the lists.

cleros
  • 4,005
  • 1
  • 20
  • 30
1

See this idea

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

class Particle:
    def __init__(self, mass, acceleration, position, velocity):
        self.position = [None, position,None]
        self.velocity = [None, velocity, None]
        self.acceleration = [None, acceleration, None]
        self.mass = mass

particles    = []
position     = Vector(-0.002893107099833329, 0, 0)
velocity     = Vector(0, 0, 0) # at rest
mass         = sunMass
acceleration = initialAcceleration

particle.append(Particle(mass, acceleration, position, velocity);
.
.
.
particle.append(Particle(otherMass, otherAcceleration, otherPosition, otherVelocity);

you can use classes this way, and further more, you can add methods to update the values, get the values, print the etc.

Iharob Al Asimi
  • 52,653
  • 6
  • 59
  • 97