Consider the following situation:
class A:
def __init__(self):
self.b_list = []
def add_element(b)
self.b_list.append(b)
class B:
def __init__(self,x):
self.x = x
class C:
def __init__(self,a,other_data):
self.a = a
def find_new_b(self):
....
def solve(c):
return c.find_new_b()
Each instance of class A has a list of instances of class B, that are added in an incremental way.
I need to iterate over all the instances of class A and find for each of them a new element of class B.
I'm using multiprocessing to do that
list_of_c_elements = [...]
pool = multiprocessing.Pool()
results = pool.map(solve, list_of_c_elements)
The problem
In results I have a list of results and I would like to understand of which instance of class A the new instance of class B belongs. Each instance of class B is generic, and I would like to keep the two classes decoupled.
Considered solution
Change solve() to:
def solve(c):
return (c.a, c.find_new_b())
I have to compare all the elements of class A I have with the one returned (very inefficient).
I cannot do something like:
for output in results:
output[0].add_element(output[1])
since the instance of class A returned is another instance.
Is there a more efficient way to achieve my goal?
C could additionally hold id(a) in a member and you can generate an index dictionary {id(a): a} if necessary. Be aware that all calls of id() must of course happen in the main process to produce usable results.
Related
I want to call a function from a class A inside another class B. However, it should be called for an object of A. I mean if I have something like this:
class A:
def __init__(self, ....):
self.valuechanged=False
# do something
objectfromb=B()
self.somearray.append(objectfromb)
def updateevent(self):
self.valuechanged=True
# do some things if update event triggered
class B:
def __init__(self,...):
self.somevalue=0
self.someothervalue=1
# do something
def updatesomevalue(self,somenewvalue):
self.somevalue=somenewvalue
# !!! HERE SHOULD BE A CALL TO CLASS A FUNCTION updateevent
And in my code I use the classes like this:
a=A()
Then i would have a list somearray in a (a.somearray) which contains an object of B. So if I want to update this object B with:
a.somearray[0].updatesomevalue(10)
Then there should not only be a new value for a.somearray[0].somevalue but also the function update event of class A should trigger changing a. How can I do that?
There are two ways I can think of to achieve this without invoking any special magic.
The first is to have objects of type B know what object A they belong to so that they can call updateevent on it. This isn't a way I'm generally a fan of as there's extra admin work to do when moving instances of B between instances of A and such. If that's not a concern then it may be the best way. You'd do that something like this (with a method on A to create a B and set the correct parent for convenience):
class A:
valuechanged=False
somearray=[]
def add_b(self):
b = B(self)
somearray.append(b)
return b
def updateevent(self):
self.valuechanged=True
class B:
somevalue=0
someothervalue=1
def __init__(self, parent):
self.parent = parent
def updatesomevalue(self,somenewvalue):
self.somevalue=somenewvalue
self.parent.updateevent()
The second is to provide a method on A that does both tasks. This is only suitable if 1) you know A will always contains instances of B and only B and 2) B's interface is relatively small (to avoid providing lots of methods of this type on A). You would implement this as something like:
class A:
valuechanged=False
somearray=[]
def updatesomevalue(self, index, new_value):
somearray[index].updatesomevalue(new_value)
self.updateevent()
def updateevent(self):
self.valuechanged=True
class B:
somevalue=0
someothervalue=1
def updatesomevalue(self,somenewvalue):
self.somevalue=somenewvalue
Something I haven't addressed is that somearray, somevalue, etc are all being created as class attributes in your example (i.e. they will be shared among all instances, instead of each instance having its own ones). This is likely not what you wanted.
I'm trying to create a list of objects (Called Super in this example) and pass an object to that object (Called Sub in this example).
However, whenever I do that, Python recognizes that each of the Super classes are individual objects, but the sub classes within are all the same. It looks like the one Sub object is the last one to be passed through and each one that gets passed through overwrites the previous.
The goal is that I would get the number back (0 - 4), but because they are all the same object, I just get the last one (4) back. What would be a solution or workaround?
driver.py
from Super import *
from Sub import *
class1 = []
class2 = []
for a in range(0,5):
class1.append(Sub(a))
for a in range(0,5):
class2.append(Super(class1[a]))
for a in range(0,5):
class2[a].printnumber()
Super.py
class Super:
def __init__(self, a):
global class1
class1 = a
def printnumber(self):
print(class1.getnumber())
Sub.py
class Sub:
def __init__(self, a):
global number
number = a
def getnumber(self):
return number
You may be confusing global variables with member variables. If each instance of a class should have its own copy of a variable, you should do it like this:
class Sub:
def __init__(self, a):
self.number = a
def getnumber(self):
return self.number
The self describes that you assign it to your object.
If you use global, the variable is shared over all instances. Generally you should avoid using global, since it is almost always possible to achieve the same thing in a significantly cleaner way!
I asked about this yesterday, but I botched writing up my question so much that by the time I realized what I typed, all the replies were solutions to a different miss-worded problem I didn't have. Sorry for the foolish type up last time.
I have two Classes, and I want them to able to share a common list without having to pass it as a parameter. I also want to create a method that will scramble that list, and I want the list to be the same newly scrambled list in both Class A and Class B.
I figured this was a case for inheritance, so I made a Parent Class and set the list as a class attribute and made a method to scramble, but the list variable is oddly enough being now treated as an instance variable of the children.
class A:
lst = []
target = 0
def generateNewLst(self, randomRange, listSize):
self.lst = [random.randint(*randomRange) for i in range(listSize)]
class B(A):
pass
class C(A):
pass
My inherited method works just fine:
a = B()
a.generateNewLst((0, 10), 3)
a.lst # => [2,5,7]
but when I create another B:
b = B()
b.lst # => [] not shared when I want it to be
This CANNOT be solved with a class attribute in B, because that won't solve the more important below issue...
c = C()
c.lst # => [] not shared when I want it to be
TL;DR: I want a Class attribute that shares between every instance of both classes. I want a.lst == b.lst == c.lst every time I run generateNewList on ONE of any of those instances.
How should I reorganize my setup to work the way I want it to?
You need a static variable. To do so make the method generateNewLst static and let him update the static variable lst and not a member variable lst that would belong to the instance of the class and not to the class itself.
class A:
lst = []
#staticmethod
def generateNewLst(randomRange, listSize):
A.lst = [random.randint(*randomRange) for i in range(listSize)]
class B(A):
pass
class C(A):
pass
Then once you generate the lst you will have it for all classes.
a = B()
B.generateNewLst((0, 10), 3)
# the same list is available for all classes
print(A.lst)
print(B.lst)
print(C.lst)
Please guide to an explain of the difference between
object = class()
and
var = class method returning a class:
class Countsome(object):
#classmethod
def get(cls, x, y):
self = cls()
sum = self.add2(x, y)
print sum
return cls
def add2(self, x, y):
sum = x+y
return sum
xyz = Countsome.get(5, 9)
==========================================
class CountSome(object):
def __init__(self):
pass
def add2(self, x, y):
sum = x+y
print sum
xyz = CountSome()
xyz.add2(5, 9)
Looking to understand where I should use one, I am just printing the sum so not returning, so please assume I am asking this question for these kind of tasks(where returning results like sum is not important).
And looking for answers like, which one would be efficient, when.
What are the benefits of each and scenarios best suited for each. Guide to a source if possible
You kinda get it wrong. classmethod should be use when you need to perform action that doesn't need an instance but does need the cls object:
A class method receives the class as implicit first argument, just like an instance method receives the instance.
For example, if you have a COUNTER object in your class which counts how many instances were instantiated.
The second code is actually using staticmethod; that is a method defined in a class but don't need access to any class / instance attributes. staticmethod can be defined outside of a class but resides in it for convenience
My Class:
class myClass:
pass
I am looking to recreate this effect:
x = myClass()
y = myClass()
z = myClass()
within a for loop because the number of times I need to loop will be varied each time.
Trying this:
x = 3
for i in range(x):
cls = myClass()
doesn't work because on each iteration I recreate the class instance.
My thinking is that on each loop I need to create a copy of the class and store that in a dict for referencing. So my questions are:
Is this the right approach?
How do I create a copy of a class?
My attempts to create a class so far have been unsuccessful as the class isn't totally individual.
x = deepcopy(cls)
CopyOfCls = type('CopyOfCls', cls.__bases__, dict(cls.__dict__))
EDIT: Answerers revealed that I was actually looking at creating multiple class instances.
You don't need to copy a class to make multiple instances of that class.
items = []
for i in range(10):
items.append(myClass())
items now contains ten separate myClass instances. You can access them individually with indexing, ex. items[3].