étale-cohomology étale-cohomology - 1 month ago 15
Python Question

Shortest example of a class with two "synchronized" variables

I'm trying to implement the simplest possible example of a class that represents a (geometric) circle and can print its own data.

Circle
is a class with two variables,
self.radius
and
self.area
. The only requirement is that, when changing one variable, the other changes too.

What's the absolute simplest way to do this? Is it with the
property
decorator?

Here's my attempt.

import math


class Circle:

def __init__(self, radius=1):
self._radius = radius
self._area = math.pi * radius**2

@property
def radius(self):
return self._radius

@radius.setter
def radius(self, radius):
self._radius = radius
self._area = math.pi * radius**2

@property
def area(self):
return self._area

@area.setter
def area(self, area):
self._area = area
self._radius = math.sqrt(area / math.pi)

def __repr__(self):
return 'radius {:.2f} area {:.2f}'.format(self._radius, self._area)


c = Circle()
print(c)

c.radius = 110
print(c)

c.area = 3
print(c)


I'm curious if there's a way to accomplish the same thing in less lines of code, or if this is the best that can be done.

Answer

A simpler way would be only using a single attribute inside the class, and providing the second by calculating it from the first upon request.

import math

class Circle:
    def __init__(self, radius=1):
        self.radius = radius

    @property
    def area(self):
        return math.pi * self.radius**2

    @area.setter
    def area(self, area):
        self.radius = math.sqrt(area / math.pi)

    def __repr__(self):
        return 'radius {:.2f}  area {:.2f}'.format(self.radius, self.area)


c = Circle()
print(c)

c.radius = 110
print(c)

c.area = 3
print(c)

Furthermore, if less lines of code is the goal, we can shorten the area property code bit, see the following modified code:

import math

class Circle:
    def __init__(self, radius=1):
        self.radius = radius

    def area_set(self): self.radius = math.sqrt(area / math.pi)
    area = property(fget=lambda self: math.pi * self.radius**2, fset=area_set)

    def __repr__(self):
        return 'radius {:.2f}  area {:.2f}'.format(self.radius, self.area)


c = Circle()
print(c)

c.radius = 110
print(c)

c.area = 3
print(c)
Comments