Reputation: 85
How can I use some class attribute within a thread that calls other methods without editing the initial value and without passing the attribute as a parameter?
"First" and "second" value must always be equal to "init" value, and "third" and "fourth" must be both equal.
This example shows the initial problem:
from concurrent.futures import ThreadPoolExecutor
from random import random
from time import sleep
class main():
def __init__(self):
self.var = random()
print('init', self.var)
def first(self):
print('first', self.var)
self.second()
print('fourth', self.var)
def second(self):
print('second', self.var)
self.var = random()
print('third', self.var)
sleep(1)
m = main()
with ThreadPoolExecutor() as executor:
executor.submit(m.first)
executor.submit(m.first)
executor.submit(m.first)
Assigning self.var to another attribute withing the method doesn't obviously work:
class main():
def __init__(self):
self.var = random()
print('init', self.var)
def first(self):
self.var2 = self.var
print('first', self.var2)
self.second()
print('fourth', self.var2)
def second(self):
print('second', self.var2)
self.var2 = random()
print('third', self.var2)
sleep(1)
The only solution I tried is assigning the attribute to a local variable and passing it to the called function as a parameter. This is not a good solution in my case because I need to pass lots of attributes and the code rapidly increase and begin less readable.
class main():
def __init__(self):
self.var = random()
print('init', self.var)
def first(self):
var = self.var
print('first', var)
var = self.second(var)
print('fourth', var)
def second(self, par):
print('second', par)
par = random()
print('third', par)
sleep(1)
return par
Can you think of a pythonic way to use the attribute instead of the local variable passed as parameter?
EDIT: I've just found out a new way to face the problem: using "nonlocal" statement and nesting the functions, what do you think about it?
class main():
def __init__(self):
self.var = random()
print('init', self.var)
def first(self):
var = self.var
print('first', var)
def second():
nonlocal var
print('second', var)
var = random()
print('third', var)
sleep(1)
second()
print('fourth', var)
Upvotes: 1
Views: 3659
Reputation: 16172
If you just want to have separate state for each tread, you can create and pass different objects into each thread:
from concurrent.futures import ThreadPoolExecutor
from random import random
from time import sleep
class main():
def __init__(self):
self.var = random()
print('init', self.var)
def first(self):
print('first', self.var)
self.second()
print('fourth', self.var)
def second(self):
print('second', self.var)
self.var = random()
print('third', self.var)
sleep(1)
def worker():
m = main()
m.first()
with ThreadPoolExecutor() as executor:
executor.submit(worker)
executor.submit(worker)
executor.submit(worker)
Upvotes: 3