1

Suppose I have the following code:

import pandas as pd
import cx_Oracle

class Foo:

    instances = []

    def __init__(self, id, name):
        self.id = id
        self.name = name

        dsn_tns = cx_Oracle.makedsn('***', '***', service_name='***')
        conn = cx_Oracle.connect(user=r'***', password='***', dsn=***)

        self.data = pd.read_sql(***, conn)
        conn.close()

        Foo.instances.append(self)

    def method1(...):
        ...

    def method2(...):
        ...


one = Foo(1, 'one')

Where I create a class and initialize one (or potenitally more) instances of that class.

In this case I am importing some data from an oracle server which takes a long time for the SQL query to run.

Say I run method1 on my object:

one.method1...

after running this say I decide I want to use method2 on one:

one.method2...

Now I will have to run the code again which will have to reinitialize one as an instance of the class Foo, which will force the SQL query to rerun which takes time. It will also rerun method1 on one which may also take a long time.

I am a beginner so I am wondering what is the best way around this?

Something like storing one in memory so when I rerun the code it doesn't have to initialize one again and applies the method directly to the object in memory?

Also is there a way to store potential outputs of method1 so when I run

one.method1
one.method2

It doesn't have to re-do one.method1 if it has been run previously.

Obviously this is not a problem on things that run fast but on code with many methods and many objects in a class and many classes etc. I can imagine this would become overwhelming.

I am sure a solution and best practices do exist but I am struggling to find help on this issue.

I suspect this is a general thing with all OOP and not just python.

Thank you.

user9940344
  • 574
  • 1
  • 8
  • 26
  • 1
    Remove `Foo.instances.append(self)` make `self.data` a `class variable` and run all `oracle` dependent by condition only the **first** time. E.g `if not Foo.data: ...` – stovfl Sep 13 '19 at 13:05

2 Answers2

0

If you avoid changing your class instace's data when calling one of the methods, you simple can run either of the methods, nothing will change for one. This is obvious.

If the methods you are calling in fact do make changes to some member variables of your class, you can make a copy of the instance:

import copy

...
one = Foo(1, 'one')
one_bak = copy.copy(one)
one.method1
one = one_bak
one.method2
AnsFourtyTwo
  • 2,480
  • 2
  • 13
  • 33
  • But you still have to initialize one. You say `one = Foo(1, 'one')` so each time I run this I will still have to initialize one, correct?. This is precisely what I want to understand how to avoid. – user9940344 Sep 13 '19 at 11:59
  • If you want to have an instance from the Foo() class and for constructing the instance an SQL query is needed. Yes, you have to initialize `one` at least once. You can think about making Foo() "lazy" and start the SQL query upon request. – AnsFourtyTwo Sep 13 '19 at 12:02
  • You say I have to initialize `one` at least once, but won't your code initialize it each time the code is run? To be clear I only want to have to initialize it once and then be able to apply methods to the data as much as I want without having to re-initialize. – user9940344 Sep 13 '19 at 12:05
  • In that case, you need to serialize and store your objects. See answer of @Syzmon Maszke – AnsFourtyTwo Sep 13 '19 at 12:12
0

In principle, memory is connected to your Python program (see this answer for example and this thread for possible solutions).

Easiest would be to pickle your object and unpickle it if file is available. See Python documentation for more information.

Szymon Maszke
  • 22,747
  • 4
  • 43
  • 83