Excelsior
Excelsior

Reputation: 121

Python: How to Encapsulate a Variable Across Multiple Classes?

I have a script using threaded timers that manipulates 2 common lists at random.

Because the class instances manipulate the lists on threaded timers, I cannot pass the variables to the classes & back.

…All instances of the classes need to manipulate a single, up to date list.

Because of that, the scope of those lists are set to global. However, I need the scope to be at the class level, yet be manipulated by multiple classes.

To clarify...

Here's the basic program structure:

Global list variable_1
Global list variable_2

class MasterClass:
    # this creates instances of the threaded classes. 
    There are 50+ instances of MasterClass creating thousands
    of instances of ThreadedClass1, 2, & 3.  All manipulate
    global list variables 1 & 2.

class ThreadedClass1:
    # threaded classes manipulate global list variables 1 & 2 on random timers.

class ThreadedClass2:

class ThreadedClass3:

The problem: For each instance of MasterClass I need a separate list variable 1 & 2. Each instance of ThreadedClasses called by that instance of MasterClass must manipulate only the list variables owned by that instance of MasterClass.

Basically I need the equivalent of a global list variable, but I need it to be encapsulated by an instance of MasterClass, and be manipulated by any instance of ThreadedClasses called by that instance of MasterClass only.

How's this done?

Upvotes: 1

Views: 2264

Answers (2)

stalk
stalk

Reputation: 12054

Try to pass instance of MasterClass to every produced instance of ThreadedClasses.

Then, define thread save methods in MasterClass, that will perform manipulation with your variable_1, variable_2. ThreadedClasses shall not touch this lists directly, only by calling those methods.

Small example (check subclassing from object):

import threading


class ThreadedClassBase(object):
    def __init__(self, master, *args, **kwargs):
        self.master = master

    def do_something(self):
        self.master.append(1, 'some_value')
        value = self.master.getitem(1, 0)


class ThreadedClass1(ThreadedClassBase):
    def __init__(self, *args, **kwargs):
        super(ThreadedClass1, self).__init__(*args, **kwargs)
        # ...

# same for ThreadedClass2, 3


class MasterClass(object):
    def __init__(self, *args, **kwargs):
        self.variable_1 = list()
        self.variable_2 = list()
        self.lock = threading.Lock()
        for i in range(50):
            ThreadedClass1(master=self)
            # create new thread

    def append(list_nb, value):
        with self.lock:
            getattr('variable_' + list_nb).append(value)

    def getitem(list_nb, index):
        with self.lock:
            return getattr('variable_' + list_nb)[index]

Upvotes: 1

John La Rooy
John La Rooy

Reputation: 304147

If I understand correctly, you should be able to make them instance variables of MasterClass and pass them into the constructors.

eg.

class MasterClass:
    def __init__(self):
        self.variable_1 = [...]
        self.variable_2 = [...]
        self.tc1 = ThreadedClass1(self.variable_1, self.variable_2)
        self.tc2 = ThreadedClass2(self.variable_1, self.variable_2)
        self.tc3 = ThreadedClass3(self.variable_1, self.variable_2)

Alternatively pass the whole instance in

class MasterClass:
    def __init__(self):
        self.variable_1 = [...]
        self.variable_2 = [...]
        self.tc1 = ThreadedClass1(self)
        self.tc2 = ThreadedClass2(self)
        self.tc3 = ThreadedClass3(self)

class ThreadedClass1:
    def __init__(self, parent):
        self.mc = parent

etc.

Upvotes: 0

Related Questions