class Circle:
    def __init__(self, radius):
        # keine normale Attributzuweisung
        # versteckter Aufruf einer Funktion
        self.radius = radius

    @property
    def radius(self):
        print("Getting the radius")
        return self.__radius

    @radius.setter
    def radius(self, radius):
        print("Setting a new radius")
        assert radius > 0, "Radius has to be positive"
        self.__radius = radius

    @property
    def diameter(self):
        return 2 * self.radius

    @diameter.setter
    def diameter(self, d):
        self.radius = d / 2

    @property
    def area(self):
        # keine teuren/langsamen operationen geschehen
        return self.calc_area()

    def calc_area(self):
        area = 3.14 * self.radius ** 2
        return area

    def calc_perimeter(self):
        return 3.14 * self.diameter

    # muss str zurück geben
    def __repr__(self):
        return f"Circle(radius={self.radius})"

if __name__ == "__main__":
    c1 = Circle(2)
    print(c1.radius)
    c1.radius += 0.5
    print(c1.diameter)
    c1.diameter -= 1
    print(c1)  # -> entweder __str__ oder __repr__ definierens
    c2 = Circle(2)
    print(c1 == c2)
    #  beides verbinden -> properties
    # als dataclasses!