TAGS :Viewed: 7 - Published at: a few seconds ago

[ When to store things as part of an instance vs returning them? ]

I was just wondering when to store things as part of a class instance versus when to use a method to return things. For example, which of the following would be better:

class MClass():

    def __init__(self):
        self.x = self.get_x()
        self.get_y()
        self.z = None
        self.get_z()

    def get_x(self):
        return 2

    def get_y(self):
        self.y = 5 * self.x

    def get_z(self):
        return self.get_x() * self.x 

What are the conventions regarding this sort of thing and when should I assign things to self and when should I return values? Is this essentially a public/private sort of distinction?

Answer 1


  1. You shouldn't return anything from __init__.
  2. Python is not Java. You don't need to include get for everything.
  3. If x is always 2 and y is always 10 and z is always 12, that is a lot of code.

Making some assumptions, I would write that class:

class MClass(object):

    def __init__(self, x):
        self.x = x

    def y(self):
        return self.x * 5

    def z(self):
        return self.x + self.y()

>>> c = MClass(2)
>>> c.x
2
>>> c.y() # note parentheses
10
>>> c.z()
12

This allows x to change later (e.g. c.x = 4) and still give the correct values for y and z.

Answer 2


There's no "conventions" regarding this, AFAIK, although there're common practices, different from one language to the next.

In python, the general belief is that "everything is public", and there's no reason at all to have a getter method just to return the value of a instance variable. You may, however, need such a method if you need to perform operations on the instance when such variable is accessed.

Your get_y method, for example, only makes sense if you need to recalculate the expression (5 * self.x) every time you access the value. Otherwise, you should simply define the y variable in the instance in __init__ - it's faster (because you don't recalculate the value every time) and it makes your intentions clear (because anyone looking at your code will immediately know that the value does not change)

Finally, some people prefer using properties instead of writing bare get/set methods. There's more info in this question

Answer 3


I read your question as a general Object Oriented development question, rather than a python specific one. As such, the general rule of member data would be to save the data as a member of the class only if it's relevant as part of a particular instance.

As an example, if you have a Screen object which has two dimensions, height and width. Those two should be stored as members. The area associated with a particular instance would return the value associated with a particular instance's height and width.

If there are certain things that seem like they should be calculated on the fly, but might be called over and over again, you can cache them as members as well, but that's really something you should do after you determine that it is a valid trade off (extra member in exchange for faster run time).

Answer 4


You can use the @property decorator:

class MClass():

    def __init__(self):
        self.x = 2

    @property
    def y(self):
        return 5 * self.x

    #here a plus method for the setter
    @y.setter
    def y(self,value):
        self.x = y/5   

    @property    
    def z(self):
        return self.x * self.x 

It's a good way of organizing yours acessors

Answer 5


get should always do what it says. get_y() and get_z() don't do that.

Better do:

class MClass(object):
    def __init__(self):
        self.x = 2

    @property
    def y(self):
        return 5 * self.x

    @property
    def z(self):
        return self.x * self.x

This makes y and z always depend on the value of x.

You can do

c = MClass()
print c.y, c.z # 10, 4
c.x = 20
print c.y, c.z # 100, 400