I am trying to load a whole class instance via dill rather than dump and load each class variable one at a time.
Can anybody show me how to do this:
class Object(object):
pass
class ClassA:
def __init__(self):
self.DATA = "Initial"
class ClassB:
def __init__(self, CA):
self.CA = CA
def updateValue(self):
#a = dill.load(ClassA.storage)
a = Object()
a.DATA = "new value"
self.CA = a
print self.CA.DATA
CA = ClassA()
CB = ClassB(CA)
CB.updateValue()
print CA.DATA
So that the output is:
new value
new value
I think you're asking:
Given object A and object B, how can I copy all of A's attributes to B in one step (or programatically)?
Naive approach:
B.__dict__ = dict(A.__dict__) # make a copy so objects don't share same dict
The problem with this approach is that it clobbers any preexisting attributes in B that did not exist in A. eg.
B.attr = "some value"
B.__dict__ = dict(A.__dict__)
print(hasattr(B, "attr")) # expect False
A better approach. This approach copies over A's attributes and leaves any attributes that exist on B, but not on A, alone.
B.__dict__.update(A.__dict__)
However, there are still problems if there are attributes on A's class and its parent classes that you want to copy over. But I think that's a different question.
In your updateValue
def updateValue(self):
self.ca.DATA = "new value"
Related
For some reason, I need to be able to delete all the children (in some sense) that were originated by some method of the class. Here is an example:
class A():
def __init__(self):
self.a_val = 56
self.children = list()
def __del__(self):
del self.children
def gen_b(self):
return B(self.a_val)
class B():
def __init__(self, val):
self.a_val = val
self.b_val = 87
What I want is somehow to append generated class B from gen_b to A().children so that:
a_class = A()
b_generated = a_class.gen_b()
del a_class
# b_generated is also deleted
Additionally, I need this for cython (I use cdef classes), so maybe there are some solutions with __dealloc__ or other Cython specific notations. All the solutions will be appreciated.
What I want is somehow to append generated class B from gen_b to A().children
Just store the new element before returning it and you can do whatever you want with it - including adding to children
def gen_b(self):
b = B(self.a_val)
self.children.append(b)
return b
As for del... Please read what del actually does. The most important part is:
Deletion of a name removes the binding of that name
So if you do e.g.
>>> a_class = A()
>>> a2 = a_class
>>> del a_class
a2 still will work and target the same element (because it holds the same reference that a_class did). del just deletes the name, not the object itself.
You would need a different approach to delete those elements.
So I have an idea in mind for a project, but i would need to have 2 instances of a certain class output into eachother. I want to make it so that the instance something gets its input from is an attribute of the instance, for example:
class Class(object):
def __init__(self, input):
self.input = input
a = Class(b)
b = Class(a)
Where "Class"is the class that these instances are from.
I hope my question makes my point clear, thanks in advance for your help!
Well, you could design the class constructor in such a way that by default an instance creates its own self-referential input instance:
class Class(object):
def __init__(self, input=None):
if input None:
self.input = Class(self)
else:
self.input = input
>>> a = Class()
>>> b = a.input
>>> b.input is a
True
Or, make it more explicit and just set the input on the first instance after creating the second:
class Class(object):
def __init__(self, input=None):
self.input = input
>>> a = Class()
>>> b = a.input = Class(a)
>>> a.input is b
True
>>> b.input is a
True
I'm afraid you won't be able to pass object b to the constructor of object a before the object b is created. Of course you may try:
a = Class(Class(b(a))
to pass just created b to the constructor of a but this time you's want to pass not-yet-created object a to the constructor of a. This won't work either.
But that's only one battle is lost. To win the war you may try:
a = Class()
b = Class()
a.input = b
b.input = a
Now they can talk to each other.
If you still want to save two lines of code, you may pass a to the constructor of b which will attach newly created b (that means self) to a and vice versa. Constructor of a will be given empy object so it won't do any connection util b gets a to do so.
But to make the code clear I'd prefer the first solution.
I just started to learn Python and I"m struggling a little with instance variables. So I create an instance variable in a method that's of a list type. Later on, I want to call and display that variable's contents. However, I'm having issues doing that. I read some online, but I still can't get it to work. I was thinking of something along the following (this is a simplified version):
What would the proper way of doing this be?
class A:
def _init_(self):
self.listVar = [B("1","2","3"), B("1","2","3")]
def setListVal():
#Is this needed? Likewise a "get" method"?
def randomMethod():
A.listVar[0] #something like that to call/display it right? Or would a for
#for loop style command be needed?
Class B:
def _init_(self):
self.a = ""
self.b = ""
self.c = ""
Is the list something you'll be passing to the instance when you create it (i.e. will it be different each time)?
If so, try this:
class A:
def __init__(self, list):
self.listVar = list
Now, when you instantiate (read: create an instance) of a class, you can pass a list to it and it will be saved as the listVar attribute for that instance.
Example:
>>> first_list = [B("1","2","3"), B("1","2","3")]
>>> second_list = [C("1","2","3"), C("1","2","3")]
>>> first_instance = A(first_list) # Create your first instance and pass it your first_list. Assign it to variable first_instance
>>> first_instance.listVar # Ask for the listVar attribute of your first_instance
[B("1","2","3"), B("1","2","3")] # Receive the list you passed
>>> second_instance = A(second_list) # Create your second instance and pass it your second_list. Assign it to variable second_instance
>>> second_instance.listVar # Ask for the listVar attribute of your second_instance
[C("1","2","3"), C("1","2","3")] # Receive the list you passed second instance
Feel free to ask if anything is not clear.
class A:
def __init__(self):
self.listVar = [B("1","2","3"), B("1","2","3")]
def setListVal(self, val):
self.listVar[0] = val # example of changing the first entry
def randomMethod(self):
print self.listVar[0].a # prints 'a' from the first entry in the list
class B:
def __init__(self, a, b, c):
self.a = a
self.b = b
self.c = c
I made several changes. You need to use self as the first argument to all the methods. That argument is the way that you reference all the instance variables. The initialization function is __init__ note that is 2 underscores before and after. You are passing three arguments to initialize B, so you need to have 3 arguments in addition to self.
I have two classes, A and B, B being a subclass of A. First an instance A is initialized and passed a certain name of the user's choice. Then an arbitrary number of instances of B are created, and they are initialized with the name of the superclass A of which they belong to. How would I go about sending information from each instance of B to A assuming there is an instance of A with the name designated in the initialization of B?
class A:
def __init__(self,name):
self.name=name
class B(A):
def __init__(self,someinfo,A_name):
self.someinfo=someinfo
self.A_name=A_name
How would I go about sending the attribute 'someinfo', or by that matter any information, from B to the given instance of A?
you can initialize B with an instance of a
class B:
def __init__(self, someinfo, a_instance):
self.someinfo = someinfo
self.a_instance = a_instance
def send_message_to_a(self):
self.a_instance.a_function(self.someinfo)
a = A()
bs = [B('hi', a) for i in range(random.randint(1, 10))]
for b in bs:
b.send_message_to_a() # calls the a function passing someinfo
Additionally, as you have it setup B doesn't seem to be a subclass of A at all?
i have a question about class attribute in python.
class base :
def __init__ (self):
pass
derived_val = 1
t1 = base()
t2 = base()
t2.derived_val +=1
t2.__class__.derived_val +=2
print t2.derived_val # its value is 2
print t2.__class__.derived_val # its value is 3
The results are different. I also use id() function to find t2.derived_val and t2.__class__.derived_val have different memory address.
My problem is derived_val is class attribute. Why it is different in above example?
Is it because the instance of class copy its own derived_val beside the class attribute?
There are class attributes, and instance attributes.
When you say
class base :
derived_val = 1
You are defining a class attribute. derived_val becomes a key in
base.__dict__.
t2=base()
print(base.__dict__)
# {'derived_val': 1, '__module__': '__main__', '__doc__': None}
print(t2.__dict__)
# {}
When you say t2.derived_val Python tries to find 'derived_val' in t2.__dict__. Since it is not there, it looks if there is a 'derived_val' key in any of t2's base classes.
print(t2.derived_val)
print(t2.__dict__)
# 1
# {}
But when you assign a value to t2.derived_val, you are now adding an instance attribute to t2. A derived_val key is added to t2.__dict__.
t2.derived_val = t2.derived_val+1
print(t2.derived_val)
print(t2.__dict__)
# 2
# {'derived_val': 2}
Note that at this point, there are two derived_val attributes, but only
the instance attribute is easily accessible. The class attribute becomes accessible only through referencing base.derived_val or direct access to the class dict base.__dict__.
Check it out here and here.
The __class__ attribute is the class that the object belongs to. So in your example, the situation is similar to static variables. The t2.__class__.derived_val is referring to the variable that belongs to the class, not the variable that belongs to t2.
Another way (perhaps a more concise one) to demonstrate this:
class A():
a1 = []
x = A()
y = A()
x.a1.append("test")
x.a1, y.a1
(['test'], ['test'])
class B():
b1 = None
def __init__(self):
self.b1 = list()
r = B()
s = B()
r.b1.append("test")
r.b1, s.b1
(["test"], [])