0

consider class

class Grid():
    def __init__(self,r,z,t):
        self.rgrid = r
        self.zgrid = z
        self.tgrid = t
        self.otherstuff = long_computation(r,t,z)

class Solution(Grid):
    def __init__(self,r,g):
        self.zones = r
        Grid.__init__(self,g.r,g.z,g.t)

g = Grid(my_r,my_z,my_t)
sol = Solution(r,g)

This creates what I want, except the "long_computation" is done twice. What would be a clean way to structure the classes that would work whether I called just Grid, or whether I also did the Solution step?

Thanks, J.

3
  • 2
    Why does Solution inherit from Grid, and why does it take an existing Grid as an argument instead of r, z, and t? Commented May 24, 2017 at 23:47
  • what's the difference between r in Grid.__init__ and in Solution.__init__? it seems like last one should be named zones Commented May 25, 2017 at 3:35
  • You can have a class variable done_long_computation which you'd set the first time __init__ is executed, and __init__ checks if done_long_computation is set. Commented May 25, 2017 at 20:21

4 Answers 4

1

You can have a method to perform calculation in parent class. Using this you can call the method and compute the stuff which takes long time when you want to calculate it.

class Grid():
    def __init__(self,r,z,t):
        self.rgrid = r
        self.zgrid = z
        self.tgrid = t

    def start_long_computation(self):
        self.otherstuff = long_computation(self.rgrid,self.tgrid,self.zgrid)

call the start_long_computation in Solution instance

class Solution(Grid):
    def __init__(self,r,my_r ,my_z ,my_t):
        self.zones = r
        Grid.__init__(self, my_r ,my_z ,my_t)
        Grid.start_long_computation(self)

You can now access otherstuff using self.otherstuff in Solution instance

or

class Grid():
    def __init__(self,r,z,t):
        self.rgrid = r
        self.zgrid = z
        self.tgrid = t

    def start_long_computation(self):
        return long_computation(self.rgrid,self.tgrid,self.zgrid)

class Solution():
    def __init__(self,r,g):
        self.zones = r
        self.otherstuff = g.start_long_computation()

g = Grid(my_r,my_z,my_t)
sol = Solution(r,g)
Sign up to request clarification or add additional context in comments.

2 Comments

Hi, is there a way to for Solution to know if otherstuff has been created already? Sometimes I will want to use Grid and have it run the long-computation without calling it as part of Solution. Sometimes I will want to call Grid without calling Solution. Maybe subclass() ... hm. I just saw dict.keys()
You can use self.__dict__ to see if the attribute exists for the class and calculate if necessary.
1
  • IMO you should avoid any computations inside of __init__ and only do attributes assigning, so if you wanna do long_computation once and use its result you can do it outside of __init__ and pass as argument.

  • If you are not using Python 3 you probably should inherit you base class Grid from object type (in Python 3 all classes are inherited from object by default). And there is function named super and you probably should use it like super(Solution, self).__init__ (or just super().__init__ in Python 3) instead of writing Grid.__init__.

  • Passing Grid instance to initialize Solution object looks ugly, why not passing required Grid attributes? Also your example will not work since Grid objects doesn't have r, z, t fields, but rgrid, zgrid, tgrid. If you need to construct Solution instance from Grid you can write custom constructor (e.g. there are many of them in datetime.datetime type).

Considering all this remarks

class Grid(object):
    def __init__(self, r, t, z, otherstuff):
        self.rgrid = r
        self.tgrid = t
        self.zgrid = z
        self.otherstuff = otherstuff


class Solution(Grid):
    def __init__(self, zones, r, t, z, otherstuff):
        self.zones = zones
        super(Solution, self).__init__(r, t, z, otherstuff)

    @classmethod
    def from_grid(cls, zones, grid):
        return cls(zones, grid.rgrid, grid.tgrid, grid.zgrid, grid.otherstuff)


otherstuff = long_computation(my_r, my_t, my_z)
g = Grid(my_r, my_t, my_z, otherstuff)
sol = Solution.from_grid(r, g)

1 Comment

Thanks, for pointing me to super() ... and then discovering mysteries of old-style classes vs new. The classmethod device is also new to me and will be useful. In some more detail, my "otherstuff" is more like two dozen values: grid.o1, grid.o2, grid.o3, grid.o4, grid.o5,..... etc. I don't want to have to type all of those in the main code each time. But I can use the classmethod to keep the main code clean. Appreciate the update.
0

The quick, dirty way would be to add a "new" parameter to the initialization:

def long_computation(r, t, z):
    print "Oh, the despair of wasted time!", r, t, z

class Grid():
    def __init__(self,r,z,t, new_grid=True):
        self.rgrid = r
        self.zgrid = z
        self.tgrid = t
        if new_grid:
            self.otherstuff = long_computation(r,t,z)

class Solution(Grid):
    def __init__(self,r,g):
        self.zones = r
        Grid.__init__(self, g.rgrid, g.zgrid, g.tgrid, False)
        # Inherit long computation from parent.
        self.otherstuff = g.otherstuff

my_r = 77
my_z = 18
my_t = 6.2
r = 0.333

g = Grid(my_r,my_z,my_t)
sol = Solution(r,g)

Another possibility is to memoize longcomputation.

Does that help at all? I know it's not aesthetically satisfying, but it gets the job done.

Comments

0

Hm, this looks pretty ugly but builds on the above:

class Grid(object):
    def __init__(self,r,z,t):    
        self.rgrid = r
        self.zgrid = z
        self.tgrid = t       

        if "otherstuff" not  in self.__dict__.keys(): 
            self.otherstuff = self.long_computation(r,t,z)
        else:
            print "No Need to Call"

    def long_computation(ggg,r, t, z):
        return 123456

class Solution(Grid):
    def __init__(self,r,g):
        self.zones = r

    if "otherstuff" in g.__dict__.keys(): 
       self.otherstuff = g.otherstuff

    super(Solution, self).__init__(g.rgrid,g.zgrid,g.tgrid)

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.