[Tutor] Concept related to python classes

Alan Gauld alan.gauld at yahoo.co.uk
Mon Sep 7 04:16:14 EDT 2020


On 07/09/2020 06:17, Manprit Singh wrote:
> Dear Sir ,
> 
> Consider a problem to find the area of a triangle , using classes .
> self.a,  self.b, self.c are instance variables representing 3 arms of
> triangle.
> I need an instance variable self.area that represents the area of the
> triangle.

Do you really? If you can calculate the area on demand then
you don't need an instance variable you just need a method.
The more instance variables you store the bulkier your objects
become and the easier it is to get those variables in an
inconsistent state. Keep the instance variables to the
minimum that you need to support the methods. Let users
of your classes access  them via messages/methods.


> class Area:

Why have you called it class area? Surely the object here
is the triangle so this should e class Triangle?

>     def __init__(self, a, b, c):
>         self.a = a
>         self.b = b
>         self.c = c
>         self.calculate()
> 
>     def calculate(self):
>         s = (self.a + self.b + self.c) / 2
>         self.area =  (s * (s - self.a) * (s - self.b) * (s - self.c))**0.5

calculate() is really calculating the area of the triangle
so this should be your self.area() method.

> tri = Area(4, 4, 3)     # Object initialization
> print(tri.area)           #Will print 5.562148865321747 (area when arms are

That then becomes:

tri = Triangle(4,4,3)
print (tri.area())

> My first question is -
> 
> The way I have used self.area as instance variable inside class definition
> .
> The point is i haven't written self.area inside the __init__( ) .
> Is it not necessary to place an instance variable inside __init__( ) ?

No, you can put instance variable creation anywhere inside the class
definition. In fact in Python you can even add instance variables to
objects outside of the class:

class C:
   def __init__(self,x): self.x = 42

c = C(7)
c.y = 66

print(c.x,c.y)   # prints 42, 66,


But this is usually a bad idea. The c.y only exists in the c instance
not in any  others you create and the methods of the class know nothing
about it so will not use it.

And this is also the problem with defining variables in non init
methods. That variable will only exist after the method is called
for the first time. The other methods will not be able to use it
safely because they font know whether it has been created yet.
That means writing a lot of try/except code into the other
methods or having a variable that only gets used by one method
which is suspect. So it is usually better to put all instance
variables into init even if you don't yet know what value to
store in them.

> My second question is :
> The way i have called self.calculate() inside the __init__( ) is ok ?
> My idea behind this is, upon calling this function inside __init__( ), the
> area
> triangle for initial values of the arms will be calculated and the
> calculated
> value of the area will be assigned to instance variable self.area.
> Is this idea correct thinking ?

Yes, and this is how to get round the problem of initialising the
new variable outside init. In practice you are including it in
init, albeit indirectly. however this brings us back to the
initial point, if you are just storing the result of a calculation
why not just use the calculation as needed? There is a tiny
performance advantage but unless you know for sure you need
that advantage its better to use the method on demand.

> My third question is :
> As you can can see i have reassigned the values of length of arms as :
> tri.a = 3
> tri.b = 4
> tri.c = 5
> and after it tri.calculate() is called , and then tri.area gives the
> desired output.

See me code above, you don't need to store the area, just call the
method area() and use it on demand. But in principle what you have
done is fine. You might consider whether you always want to change all
three values in which case you might write a convenience method called
something like resize() (or maybe reinit()) such that you can apply all
three changes in one line:

tri = Triangle(4,4,3)
print(tri.area())
tri.resize(3,4,5)
print(tri.area())

> I have not used getters & setters as python do not promote use of getters
> and setters unless otherwise these are necessarily required.

Good :-)


-- 
Alan G
Author of the Learn to Program web site
http://www.alan-g.me.uk/
http://www.amazon.com/author/alan_gauld
Follow my photo-blog on Flickr at:
http://www.flickr.com/photos/alangauldphotos




More information about the Tutor mailing list