AnFa
AnFa

Reputation: 97

How to iterate through the objects of a class

I want to make a for loop where I search all the class objects' self.name values to match a user input. Here's the code:

import json

class Planets(object):
    def __init__(self, name, radius, sgp, soi, atmo_height, moons=()):
        self.name = name
        self.radius = radius
        self.sgp = sgp
        self.soi = soi
        self.atmo_height = atmo_height
        self.moons = moons
    
    def __repr__(self):
        return  f"{self.name}, {self.radius} m, {self.sgp}, {self.soi}, {self.atmo_height}, Moons: {', '.join([moon['name'] for moon in self.moons])}"

class Moons(Planets):
    def __init__(self, name, radius, sgp, soi, atmo_height, apoapsis, periapsis):
        super().__init__(name, radius, sgp, soi, atmo_height)
        self.apoapsis = apoapsis
        self.periapsis = periapsis

    def __repr__(self):
        return  f"{self.name}, {self.radius} m, {self.sgp}, {self.soi}, {self.atmo_height}, {self.apoapsis}, {self.periapsis}"

with open('Planets.json', 'r') as p:
    planets = json.load(p)

with open('Moons.json', 'r') as m:
    moons = json.load(m)

# Planet Objects
moho = Planets(**planets["Planets"]["Moho"])
eve = Planets(**planets["Planets"]["Eve"])
kerbin = Planets(**planets["Planets"]["Kerbin"])
duna = Planets(**planets["Planets"]["Duna"])
dres = Planets(**planets["Planets"]["Dres"])
jool = Planets(**planets["Planets"]["Jool"])

#Moon Objects
gilly = Moons(**moons["Moons"]["Gilly"])
mun = Moons(**moons["Moons"]["Mun"])
minmus = Moons(**moons["Moons"]["Minmus"])
ike = Moons(**moons["Moons"]["Ike"])
laythe = Moons(**moons["Moons"]["Laythe"])
vall = Moons(**moons["Moons"]["Vall"])
tylo = Moons(**moons["Moons"]["Tylo"])
bop = Moons(**moons["Moons"]["Bop"])
pol = Moons(**moons["Moons"]["Pol"])

So, basically, the idea would be something like, user inputs the name "Jool", the for loop iterates through all objects in the Planets and Moons classes until they find an object with the value "Jool" for the "name" key.

How can I do this?

Upvotes: 1

Views: 1877

Answers (2)

jsbueno
jsbueno

Reputation: 110166

Ordinarily, taking note of all instances of a class is not done automatically by Python or other languages.

However, you can do that by adding code in the __init__ method to register each instance as it is created in a "registry"of your choice. This "registry" is any data structure which will track your instances - a simple dictionary can be enough for most cases. You can then just keep this dictionary at the module level, or as a class attribute: an attribute that is present on the class and shared across all instances.

If one is not doing some "production level code" which would have to handle all sorts of random events and misuses (for example, if one creates a Planet with a name that is already registered), the code can be quite simple.

Since the code would be common across Planets and Moons, it is a case for using class inheritance, and share the common functionality, without the functionality getting in the way of what you want to handle in Planets

class Registerable:
    registry = {}
    def __init__(self, name):
        cls = self.__class__ # optional for readability
        cls.registry[name] = self
        super().__init__()
    

class Planets(Registerable):
    registry = {}
    def __init__(self, name, radius, sgp, soi, atmo_height, moons=()):
        super().__init__(name)
        self.name = name
        self.radius = radius
        self.sgp = sgp
        self.soi = soi
        self.atmo_height = atmo_height
        self.moons = moons

...
class Moons(Planeys):
    registry = {}  # each class have to declare its own registry, otherwise they are all shared with the base class

And then you can iterate on your instances using Planets.registry and Moons.registry as normal Python dictionaries.

Upvotes: 1

Don CorliJoni
Don CorliJoni

Reputation: 248

You put all your Moons and Planets in a list.

for item in moons_planets_list:
    if item.name == user_input:
        #Do sth

Upvotes: 1

Related Questions