HiveBrain v1.2.0
Get Started
← Back to all entries
patternpythonModerate

Recording all instances of a class - Python

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
instancesallpythonrecordingclass

Problem

In a programme that I am writing, I need to loop through all the instances of a class, the way I got around this was by appending every class to a list like below:

allPeople = []
class Person:

    def __init__(self, name, age, height):
        self.name = name
        self.age = age
        self.height = height
        allPeople.append(self)

Jeff = Person("Jeff", 20, "1.6")
Bob = Person("Bob", 39, "1.4")
Helen = Person("Helen", 19, "1.3")

for person in allPeople:
    print(person.name + " is " + str(person.age))


Is this the best way of doing things or is there a built in python function for this?

Solution

Your approach is ok, but I have just one mention (this is based on personal preferences): I'd iterate over a class not a list which is defined outside it. You'll just have to define a metaclass which supports iteration.

class IterPerson(type):
    def __iter__(cls):
        return iter(cls._allPeople)

class Person(metaclass=IterPerson):
    _allPeople = []

    def __init__(self, name, age, height):
        self._allPeople.append(self)

        self.name = name
        self.age = age
        self.height = height

if __name__ == '__main__':
    Jeff = Person("Jeff", 20, "1.6")
    Bob = Person("Bob", 39, "1.4")
    Helen = Person("Helen", 19, "1.3")

    for person in Person:
        print(person.name + " is " + str(person.age))


Magic methods are always looked up on the class, so adding __iter__ to the class won't make it iterable. However the class is an instance of its metaclass, so that is the correct place to define the __init__ method.

Please note that I also put a _ in front of your list. This is how we tell python the list we'll create is private. I have also used if __name__ == "main": which is good practice (it is used to execute some code only if the file was run directly, and not imported)

Second, keep this kind of thing as simple as possible. Don't waste a lot of time and energy on something complex. This is a simple problem, keep the code as simple as possible to get the job done.

Code Snippets

class IterPerson(type):
    def __iter__(cls):
        return iter(cls._allPeople)


class Person(metaclass=IterPerson):
    _allPeople = []

    def __init__(self, name, age, height):
        self._allPeople.append(self)

        self.name = name
        self.age = age
        self.height = height

if __name__ == '__main__':
    Jeff = Person("Jeff", 20, "1.6")
    Bob = Person("Bob", 39, "1.4")
    Helen = Person("Helen", 19, "1.3")

    for person in Person:
        print(person.name + " is " + str(person.age))

Context

StackExchange Code Review Q#126100, answer score: 10

Revisions (0)

No revisions yet.