1

I have a Python program that generates a field of stars, and populates those stars with satellites. At the end of the code, I have some nested loops to print the stars and their satellites so I can debug the generator. The result is a bit bewildering. I am almost certain that my stars and satellites are generated correctly, and that the issue is in the loops. EDIT: Looks like I was wrong. Whoops.

This is the code:

for s in world.stars:
    print s.name
    for satellite in s.satellites:
        print satellite.name

world.stars is a list of Star objects, which contain lists of satellite objects. For this test, I generated three stars with two satellites each.

This is the output:

    D6
    D6-0
    D6-1
    S11-0
    S11-1
    M19-0
    M19-1
    S11
    D6-0
    D6-1
    S11-0
    S11-1
    M19-0
    M19-1
    M19
    D6-0
    D6-1
    S11-0
    S11-1
    M19-0
    M19-1

D6 is a star name, and D6-0 is a satellite name: a satellite of the D6 star. Instead of listing a star's name then its planets, it lists all planets beneath all star names. It seems that I don't understand the usage of for loops, and how each iteration is initialized. Could someone explain to me where I am wrong, or link me to a resource that could?

BONUS: In general, is there a better way than for loops?

EDIT: Full code! Huge...

class World():
    stars = []
    max_stars = 3
    used_sat_names = []
    def __init__(self):
        print 'World Created'

    def genUniverse(self):
        last_distance_from_earth = 0
        for x in xrange(0, self.max_stars):
            star = Star(last_distance_from_earth)

            satellite_max = random.randint(0,5)
            for s in xrange(0, 2):
                last_distance_from_star = 0
                satellite = Satellite(star.name, satellite_max, s)
                star.satellites.append(satellite)

            last_distance_from_earth = star.distance_from_earth    
            self.stars.append(star)


class Star(object):
    name = ''
    distance_from_earth = 0
    kind = ''
    satellites = []

    def __init__(self, last_distance):
        self.distance_from_earth = last_distance + random.randint(4,8)
        star_kind_list = (
            ('Neutron', 3, 'N'),
            ('Dwarf', 10, 'D'),
            ('Small', 22, 'S'),
            ('Medium', 30, 'M'),
            ('Large', 20, 'L'),
            ('Giant', 10, 'G'),
            ('Supergiant', 5, 'S')
        )

        kind_index = WeightedChoice(star_kind_list).nextIndex()
        self.kind = star_kind_list[kind_index][0]

        self.name = star_kind_list[kind_index][2] + '%i'%(self.distance_from_earth)
        print 'Star called %s created!'%(self.name)


class Satellite(object):
    name = ''
    star_name = ''
    distance_from_star = 0
    size = ''
    kind = '' 
    moons = []

    def __init__(self, star_name, satellite_max, satellite_number):
        self.star_name = star_name

        self.name = '%s-%s'%(star_name, satellite_number)

        satellite_size_list = (
            ('Dwarf', 10),
            ('Small', 30),
            ('Medium', 20),
            ('Large', 20),
            ('Giant', 20),
        )

        self.size = WeightedChoice(satellite_size_list).next()
        print '%s has a satellite called %s'%(self.star_name, self.name)

world = World()
world.genUniverse()

for s in world.stars:
    print s.name
    for satellite in s.satellites:
        print satellite.name
5
  • 2
    You must be using a class variable satellites, instead of instance variables. Can you show us the code for your class? Commented Jun 2, 2013 at 3:02
  • 1
    In my opinion it looks like the following problem: You print out the first world and after this all your satellites are printed out. I think you had a problem with the adding of the satellites to your worlds, so that to every world, all satellites are added. Could you try to print out the complete list with "print world.stars" Commented Jun 2, 2013 at 3:07
  • @Pacnos, Due to your suggestion, I did some deeper and tedious poking. Yes, each star has all planets, which is pretty terrifying to me. I'm going to try to post the rest of my code, but it is pretty big. Thus why I didn't do it originally. Commented Jun 2, 2013 at 3:16
  • @Volatility You may be on to something. Main code coming up, as giant as it may be. Commented Jun 2, 2013 at 3:18
  • @Wookieguy you only need to post the class that the elements in world.stars are instances of (whatever you have named it). Commented Jun 2, 2013 at 3:19

1 Answer 1

2

The problem is in your Stars class:

The line satellites = [] creates a class variable, which means that all instances of the class will share that variable. Because the satellites should be different for each star, you need an instance variable - this will allow you to have a different value for the variable for each instance.

You need to put the declaration in __init__.

class Star(object):
    # ...
    def __init__(self, last_distance):
        self.satellites = []  # this creates an instance variable
        #...

I would say that the other class variables that you create (name, distance_from_earth, and kind) need to be instance variables as well.

Sign up to request clarification or add additional context in comments.

1 Comment

Great! I did a test to see if those were instance variables back in the beginning of this project, which was obviously a faulty test based on some silly assumptions. Now I know some of the problems with my other noob-code.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.