4

I'm messing around with classes and data flow and I am having difficulties creating a list of classes inside the class (to give control of the list to the class in itself).

class Person:

    listOfPeople = []

    def __init__(self, name, age):
        self.name = name
        self.age = age
        self.listOfPeople = []
        

    def set_age(self, age):
        if age <= 0:
            raise ValueError('The age must be positive')
        self._age = age

    def get_age(self):
        return self._age
    
    def AppendList(self):
        self.listOfPeople.append(self)

    def returnList(self):
        return self.listOfPeople

    age = property(fget=get_age, fset=set_age)



john = Person('John', 18)

barry = Person("Barry", 19)

john.AppendList()

barry.AppendList()


print(Person.listOfPeople)

The output is simply

[]

Let´s use this example. I want the class Person to have a list of people. That list of people has instances of the class it's in. I want the entire program to have access to this class, regardless of having an instance initialised. Is it even possible to do what I want in Python?

My expected output is a list with the 2 instances I added to the list.

CitrusBoy
  • 105
  • 6

3 Answers3

2

Okay so you need to create the list outside the definitions first.

Then you need to change the append function to this instead, self.listOfPeople.append(self) so that the variables are added into the list when you run it your way and remove the self.listOfPeople from the __init__.

Now the listOfPeople you initialized is shared between all instances.

class Person:
    listOfPeople = []

    def __init__(self, name, age):
        self.name = name
        self.age = age
        

    def set_age(self, age):
        if age <= 0:
            raise ValueError('The age must be positive')
        self._age = age

    def get_age(self):
        return self._age
    
    def AppendList(self):
        self.listOfPeople.append(self)

    def returnList(self):
        return self.listOfPeople

    age = property(fget=get_age, fset=set_age)


john = Person('John', 18)

barry = Person("Barry", 19)

john.AppendList()

barry.AppendList()

print(Person.listOfPeople)

for i in Person.listOfPeople:
    print (i.name, i.age)

Output for first part is:

[<__main__.Person object at 0x7fcb72395150>, <__main__.Person object at 0x7fcb723954d0>]

Output for the second part is:

John 18
Barry 19
anarchy
  • 3,709
  • 2
  • 16
  • 48
  • In this case, the output is [<__main__.Person object at 0x000002555A543FA0>, <__main__.Person object at 0x000002555A543E50>] – CitrusBoy Oct 10 '22 at 13:00
  • @CitrusBoy, check https://stackoverflow.com/q/1535327/4046632 It's another matter if it is good idea for an instance of a `Person` class to know about all other instances and yet another why you need the`AppendList()` method, when you can append to list in the `__init__` – buran Oct 10 '22 at 13:04
  • @CitrusBoy I fixed it I will add the explanation now, is this what you wanted? – anarchy Oct 10 '22 at 13:07
  • This solution doesn't append the class, just its properties, which makes it impossible to iterate with a for to manipulate the data. – CitrusBoy Oct 10 '22 at 13:14
  • @anarchy I'm curious how it works, `AppendList` method appends to `self`'s namespase only, so `class Person`'s namespace seems to be untouched, but in the end printing `print(Person.listOfPeople)` retruns `[['John', 18], ['Barry', 19]]`. how does that works? – Dmitriy Neledva Oct 10 '22 at 13:31
  • @DmitriyNeledva you are only creating 1 list which is shared – anarchy Oct 10 '22 at 15:31
  • @CitrusBoy i understand what you want now, take a look at my code, it works exactly as you want. – anarchy Oct 10 '22 at 15:37
  • @anarchy oh, i get it, there is no `listOfPeople` attribute in an instance namespace, so when we use it like `self.listOfPeople.append('something')` tree search finds `listOfPeople` inside class namespace and `self.listOfPeople` actually turns into `Person.listOfPeople` and any further manipulations with it are applied to class attribute not to instance one. – Dmitriy Neledva Oct 10 '22 at 16:33
1

Just get rid of this

self.listOfPeople = []

This line overrides the class attribute and creates an instance attribute with the same name - not what you want.

gog
  • 10,367
  • 2
  • 24
  • 38
1

this code automatically adds new instances to Person.listOfPeople

class Person:

listOfPeople = []

def __init__(self, name, age):
    self.name = name
    self.age = age
    Person.listOfPeople.append(self)
    

def set_age(self, age):
    if age <= 0:
        raise ValueError('The age must be positive')
    self._age = age

def get_age(self):
    return self._age

def AppendList(self):
    self.listOfPeople.append(self)

def returnList(self):
    return self.listOfPeople

def __repr__(self):             #I've added __repr__
    return self.name+' '+str(self.age)

age = property(fget=get_age, fset=set_age)



john = Person('John', 18)

barry = Person("Barry", 19)

# john.AppendList()

# barry.AppendList()


print(Person.listOfPeople)

the output: [John 18, Barry 19] is this what you need?

Dmitriy Neledva
  • 867
  • 4
  • 10
  • This solution is good enough for show but if I later wanna use the list to access an instance, is it possible? – CitrusBoy Oct 10 '22 at 13:09
  • 1
    yes, you can iterate it and do with instances whatever you want to – Dmitriy Neledva Oct 10 '22 at 13:10
  • 1
    this is typical one for the purpose of storing instances initiated from some class inside that some class – Dmitriy Neledva Oct 10 '22 at 13:13
  • Is it possible to attribute a list to that list outside of the class? Something like `Person.listOfPeople = anotherList` ?? – CitrusBoy Oct 10 '22 at 13:24
  • yes, but in reverse way. like: `anotherList = Person.listOfPeople` here `anotherList` is variable (=reference) to object `Person.listOfPeople`, but if you need to 'fix' it (= to create new object) you've to use `copy.deepcopy()`. – Dmitriy Neledva Oct 10 '22 at 13:28
  • The reason I'm asking is that imagine I want to store this list in a database but when I restart the application, the list is refilled with the data from the database. Is it possible? – CitrusBoy Oct 10 '22 at 13:29
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/248697/discussion-between-dmitriy-neledva-and-citrusboy). – Dmitriy Neledva Oct 10 '22 at 13:31