-2

While I was skimming over this article of printing out all instances of a class: Printing all instances of a class I came across a major problem. I wanted a solution that works without having to import anything but when I tried one of the solutions:

class A:
    instances = []
    def __init__(self):
        self.__class__.instances.append(self)
print('\n'.join(A.instances)) #this line was suggested by @anvelascos

it didn't work.

This is my code:

class Planets:
    instances = []
    def __init__(self, days, p_type, distance_from_sun):
        self.lengthOfDay = days
        self.planetType = p_type
        self.distanceFromSun = distance_from_sun
        self.__class__.instances.append(self)


T = 'Terrestrial'
G = 'Gas Giant'
I = 'Ice Giant'

mercury = Planets(88, T, 0.4)
venus = Planets(225, T, 0.7)
earth = Planets(365, T, 1)
mars = Planets(687, T, 1.5)
jupiter = Planets(4333, G, 5.2)
saturn = Planets(10759, G, 9.5)
uranus = Planets(30687, I, 19.8)
neptune = Planets(60190, I, 30)

print(Planets.instances)

It gives me the message:

[<__main__.Planets object at 0x0000016715003FD0>, <__main__.Planets object at 0x0000016715003F10>, <__main__.Planets object at 0x0000016715003EB0>, 
<__main__.Planets object at 0x0000016715003E50>, <__main__.Planets object at 0x0000016715003DF0>, <__main__.Planets object at 0x0000016715003D90>, <__main__.Planets object at 0x0000016715003D30>, <__main__.Planets object at 0x0000016715003CD0>]

Do you know how to get the actual name of the instance and not whatever this is?

SkyWalker
  • 38
  • 5
  • What do you mean by the "name of the instance"? If you mean `mercury`, `venus` etc those are variable names and cannot be listed using your method. Even if it was possible you could easily do `mercury2 = mercury` which would work around your initialiser. – Selcuk Nov 22 '21 at 01:36
  • If you want the name of each planet, you need a name attribute for each instance. You'll also want to implement `__repr__` and `__str__`. – ddejohn Nov 22 '21 at 01:36
  • Instances don't have names. – juanpa.arrivillaga Nov 22 '21 at 02:11
  • Were you helped by any of the answers supplied? – ddejohn Dec 01 '21 at 04:52
  • @ddejohn I was helped by the answers supplied. Thank you – SkyWalker Dec 09 '21 at 16:11
  • @AishaNishikawa Go ahead and select one of the answers as accepted in that case. That way your question will be marked as resolved and future readers will be able to get help from this page. – ddejohn Dec 10 '21 at 16:10

2 Answers2

0

mercury, venus etc are variable names and cannot be listed using your method. Even if it was possible you could easily do mercury2 = mercury which would work around your initialiser.

This should work without any trickery (i.e. you don't need self.__class__.instances.append(self) for this to work):

for name, obj in list(globals().items()):
    if isinstance(obj, Planets):
        print(name)

This will print:

mercury
venus
earth
mars
jupiter
saturn
uranus
neptune

Or, if you want the names in a list:

variable_names = [name for name, obj in list(globals().items()) if isinstance(obj, Planets)]
Selcuk
  • 57,004
  • 12
  • 102
  • 110
0

You can achieve this by adding a planetName attribute, and implementing __repr__ and __str__ (which you should do anyway):

class Planets:
    instances = []
    def __init__(self, name, days, p_type, distance_from_sun):
        self.planetName = name
        self.lengthOfDay = days
        self.planetType = p_type
        self.distanceFromSun = distance_from_sun
        self.__class__.instances.append(self)

    def __str__(self):
        return self.planetName

    def __repr__(self):
        return f"Planet('{self}', {self.lengthOfDay}, '{self.planetType}', {self.distanceFromSun})"

Demo:

In [10]: print(Planets.instances)
[Planet('mercury', 88, 'Terrestrial', 0.4), Planet('venus', 225, 'Terrestrial', 0.7), Planet('earth', 365, 'Terrestrial', 1), Planet('mars', 687, 'Terrestrial', 1.5), Planet('jupiter', 4333, 'Gas Giant', 5.2), Planet('saturn', 10759, 'Gas Giant', 9.5), Planet('uranus', 30687, 'Ice Giant', 19.8), Planet('neptune', 60190, 'Ice Giant', 30)]

Or if you just want the names:

In [11]: for p in Planets.instances:
    ...:     print(p.planetName)
    ...:
mercury
venus
earth
mars
jupiter
saturn
uranus
neptune
ddejohn
  • 8,775
  • 3
  • 17
  • 30