In [7]:
from math import pi

In [1]:
class Circle:
    def __init__(self, radius=1):
        self.radius = radius   # Calls the radius setter method
        
    @property
    def radius(self):
        print('calling radius getter')
        return self._radius
    
    @radius.setter
    def radius(self, value):
        print('calling radius setter')
        if value < 0:
            raise ValueError("Radius cannot be negative")
        self._radius = value    
        
    @property
    def diameter(self):
        return 2 * self.radius
    
    @diameter.setter
    def diameter(self, value):
        self.radius = value / 2
    
    @property
    def area(self):
        return pi * self.radius ** 2
    
    @area.setter
    def area(self, value):
        raise AttributeError('Area not settable')
    
    # __str__() is not needed, if __repr__ is also having same implementation
    # def __str__(self):
    #     return 'Circle({})'.format(self.radius)
    
    def __repr__(self):
        return 'Circle({})'.format(self.radius)

In [2]:
c = Circle(5)


calling radius setter

In [3]:
c = Circle(-5)


calling radius setter
---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
<ipython-input-3-ed2ec340d56d> in <module>()
----> 1 c = Circle(-5)

<ipython-input-1-1d9e1d2a9db1> in __init__(self, radius)
      1 class Circle:
      2     def __init__(self, radius=1):
----> 3         self.radius = radius
      4 
      5     @property

<ipython-input-1-1d9e1d2a9db1> in radius(self, value)
     12         print('calling radius setter')
     13         if value < 0:
---> 14             raise ValueError("Radius cannot be negative")
     15         self._radius = value
     16 

ValueError: Radius cannot be negative

In [4]:
c.radius


calling radius getter
Out[4]:
5

In [5]:
c.diameter


calling radius getter
Out[5]:
10

In [8]:
c.area


calling radius getter
Out[8]:
78.53981633974483

In [9]:
c.diameter = 2


calling radius setter

In [10]:
c.radius


calling radius getter
Out[10]:
1.0

In [11]:
c.area


calling radius getter
Out[11]:
3.141592653589793

In [12]:
c.radius = -1


calling radius setter
---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
<ipython-input-12-b4ce01a9f6b5> in <module>()
----> 1 c.radius = -1

<ipython-input-1-1d9e1d2a9db1> in radius(self, value)
     12         print('calling radius setter')
     13         if value < 0:
---> 14             raise ValueError("Radius cannot be negative")
     15         self._radius = value
     16 

ValueError: Radius cannot be negative

In [13]:
c.diameter = -2


calling radius setter
---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
<ipython-input-13-9b9f22b219a2> in <module>()
----> 1 c.diameter = -2

<ipython-input-1-1d9e1d2a9db1> in diameter(self, value)
     21     @diameter.setter
     22     def diameter(self, value):
---> 23         self.radius = value / 2
     24 
     25     @property

<ipython-input-1-1d9e1d2a9db1> in radius(self, value)
     12         print('calling radius setter')
     13         if value < 0:
---> 14             raise ValueError("Radius cannot be negative")
     15         self._radius = value
     16 

ValueError: Radius cannot be negative

In [14]:
c.area = 100


---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
<ipython-input-14-912a2f133214> in <module>()
----> 1 c.area = 100

<ipython-input-1-1d9e1d2a9db1> in area(self, value)
     29     @area.setter
     30     def area(self, value):
---> 31         raise AttributeError('Area not settable')
     32 
     33     # __str__() is not needed, if __repr__ is also having same implementation

AttributeError: Area not settable

In [ ]: