-2

When i was trying to use example from textbook and trying to rearrange some lines of code for executing, I found the result was not what I expected.

There is a ''class'' which looks like below.

class Circle:
    """This class creates circle"""
    pi = 3.14159
    all_circles = []

    def __init__(self, radius):
        self.radius = radius
        self.__class__.all_circles.append(self)
    
    def area(self):
        return self.__class__.pi * (self.radius ** 2)

    @staticmethod
    def total_area():
        total =0
        for circle in Circle.all_circles:
            total += circle.area()
        return total    

    @classmethod
    def total_area2(cls):
        total = 0
        for circle in cls.all_circles:
            total += circle.area()
        return total

When I execute it.....

c1 = Circle(10)
c2 = Circle(15)
print(c1.__class__.total_area()) # get 1021.01675
print(c2.__class__.total_area()) # get 1021.01675

In my opinion, Both c1 and c2 should be independent objects.

How do the codes cause 1021.01675 by c1 and 1021.01675 by c2

but.....

c1 = Circle(10)
print(c1.__class__.total_area()) # get 314.159
c2 = Circle(15)
print(c2.__class__.total_area()) # get 1021.01675

Do I ingnore, forget or misunderstand some concepts?

My position on this problem is that the execution should be looked like....

c1 = Circle(10)
c2 = Circle(15)
print(c1.__class__.total_area()) # get 314.159
print(c2.__class__.total_area()) # get 706.85775

and.....

c1 = Circle(10)
print(c1.__class__.total_area()) # get 314.159
c2 = Circle(15)
print(c2.__class__.total_area()) # get 706.85775
Charles Duffy
  • 280,126
  • 43
  • 390
  • 441
joejoe
  • 1
  • When you read the source code to `total_area()`, with the `for circle in Circle.all_circles:`, what do you _think_ it's trying to do? – Charles Duffy Sep 06 '22 at 15:19

1 Answers1

2

Both c1.__class__ and c2.__class__ is Circle. total_area is a staticmethod: it's basically just a function that is not tied to the class. However, internally, it iterates over Circle.all_circles, which is a class attribute, not an instance attribute.

When you initialize a new circle, the line self.__class__.all_circles.append(self) registers the circle with the class. That means that total_area will look at all the circles created up to that point. That's what you see in your examples.

If you want a per-circle area, use the instance method area.

Mad Physicist
  • 107,652
  • 25
  • 181
  • 264