How to properly reinitialise python object? - python

For example, I have this class:
class A:
def __init__(self):
self.a = 10
In instance lifetime, I change the value of a to 20
test = A()
test.a = 20
In which way I can properly reinitialize this instance, to make default value?
Is the way with calling __ init__ is good?

Calling an __init__ would do the trick, but I wouldn't recommend it as it might be harder for other people reading your code to understand quickly what you're trying to do. I would create a reset() function instead:
class A:
def __init__(self):
self.a = 10
def reset(self):
self.a = 10
And now,
test = A()
test.a = 20
test.reset() # now test.a = 10
In order to avoid code duplication, you can also call the reset() function from your __init__:
class A:
def __init__(self):
self.reset()
def reset(self):
self.a = 10

Calling __init__ is like calling a second time the constructor in another language. You may not do this.
You could create a method called reset_variables, that would be called in the constructor and that you would be able to call yourself.

Related

how to know from which class instance a function is called to access the instance attributes

I want to access an attribute of the class instance that called a function :
for example:
class A:
def a(self):
return B.q
class B:
q=0
def b(self):
M=A()
return M.a()
c=B()
c.q = 6
print(c.b())
the output will be 0 but I want it to print the q attribute of the instance c of the class B which has the value 6
Pass the instance as a parameter.
class A:
def a(self, b):
return b.q
class B:
q=0
def b(self):
M=A()
return M.a(self)
c=B()
c.q = 6
print(c.b())
This appears to be very bad program design. What are you trying to accomplish with this?
You have a class attribute and an instance attribute -- in that class -- of the same name, q. This makes your code difficult to follow and to maintain.
You have method B.b instantiate an instance of class A. You immediately call A.a, which has been assigned the questionable task of returning an instance attribute from and object of class B.
Clean up your design.
Use init appropriately for each class.
Design your class methods to work appropriately with the characteristics of instances of that class. Your question strongly suggests that your design is not yet clean in your mind, nor in code.
define an init method so that you can work with the instance attributes instead of the class variable
class A:
def a(self):
return B.q
class B:
def __init__(self):
self.q = 0
def b(self):
M=A()
return M.a()
c=B()
c.q = 6
print(c.b())

Keep object reference when class is deleted?

I have a class Foo which is instantiated an indefinite number of times during my program sequence. Like so:
def main():
f = Foo()
while f.run():
del f
f = Foo()
with run() being a method that runs an decisive condition for keeping the program alive.
Now, my Foo class creates on its __init__ method two objects a and b:
Foo class
class Foo:
def __init__(self):
a = A()
b = B(a.var)
I'm looking for a way to a being declared only at the first Foo instantiation and use that same first-instantiated a at the other Foo instantiations.
Problem arises because b depends on a. I thought about a couple solutions - from playing with __new__ and __init__ to override __del__ and global variable as cache - but none of them worked.
note: A needs to be at the same module as Foo
Maybe using a class variable?
class Foo:
a = None
def __init__(self):
if not Foo.a:
Foo.a = A()
b = B(Foo.a.var)
And function B needs to check whether a is None.
If I understand you correctly, you should be able to just make a a class variable.
class Foo:
a = A()
def __init__(self):
b = B(Foo.a.var)
I'm afraid some of your requirements will make Foo extremely difficult to test. Instead, I would suggest that you move some of the dependencies from your constructor to a start class method that would be responsible for creating the initial A instance (at the same module as Foo) and then reusing that instance in a refresh method.
class Foo:
def __init__(self, a, b):
self.a = a
self.b = b
#classmethod
def start(cls):
a = A()
b = B(a.var)
return cls(a, b)
def refresh(self):
b = B(self.a.var)
return self.__class__(self.a, b)
Then, your main function would look something like:
def main():
f = Foo.start()
while f.run():
f = f.refresh()
By overwriting the f variable, you are effectively deleting the reference to the old instance which will eventually be garbage collected.

Python - method of a class with an optional argument and default value a class member

I have something like this (I know this code doesn't work, but it's the closer to what I want to achieve):
class A:
def __init__(self):
self.a = 'a'
def method(self, a=self.a):
print a
myClass = A()
myClass.method('b') # print b
myClass.method() # print a
What I've done so far, but I do not like it, is:
class A:
def __init__(self):
self.a = 'a'
def method(self, a=None):
if a is None:
a = self.a
print a
myClass = A()
myClass.method('b') # print b
myClass.method() # print a
Default arguments are evaluated at definition time. By the time the class and method are defined self.a is not.
Your working code example is actually the only clean way of achieving this behavior.
The default is evaluated at method definition time, i.e. when the interpreter executes the class body, which usually happens only once. Assigning a dynamic value as default can only happen within the method body, and the approach you use is perfectly fine.

using variables in class functions in another class (python)

I want to use the variables i have declared inside a function in one class, in another class.
For example i want to use the variable "j" in another class. Is it possible? (I read somewhere that it might have something to do with instance variables but fully couldn't understand the concept).
class check1:
def helloworld(self):
j = 5
class check1:
def helloworld(self):
self.j = 5
check_instance=check1()
print (hasattr(check_instance,'j')) #False -- j hasn't been set on check_instance yet
check_instance.helloworld() #add j attribute to check_instance
print(check_instance.j) #prints 5
but you don't need a method to assign a new attribute to a class instance...
check_instance.k=6 #this works just fine.
Now you can use check_instance.j (or check_instance.k) just like you would use any other variable.
This may seems a little bit like magic until you learn that:
check_instance.helloworld()
is completely equivalent to:
check1.helloworld(check_instance)
(If you think about it a little bit, that explains what the self parameter is).
I'm not completely sure what you're trying to achieve here -- There are also class variables which are shared by all instances of the class...
class Foo(object):
#define foolist at the class level
#(not at the instance level as self.foolist would be defined in a method)
foolist=[]
A=Foo()
B=Foo()
A.foolist.append("bar")
print (B.foolist) # ["bar"]
print (A.foolist is B.foolist) #True -- A and B are sharing the same foolist variable.
j cannot be seen by another class; however, I think you meant self.j, which can.
class A(object):
def __init__(self, x):
self.x = x
class B(object):
def __init__(self):
self.sum = 0
def addA(self, a):
self.sum += a.x
a = A(4)
b = B()
b.addA(a) # b.sum = 4
Using class inheritane it is very easy to "share" instance variables
example:
class A:
def __init__(self):
self.a = 10
def retb(self):
return self.b
class B(A):
def __init__(self):
A.__init__(self)
self.b = self.a
o = B()
print o.a
print o.b
print o.retb()

Python object instance inheriting changes to parent class by another instance

I am confused by this behaviour of Python(2.6.5), can someone shed light on why this happens?
class A():
mylist=[]
class B(A):
j=0
def addToList(self):
self.mylist.append(1)
b1 = B()
print len(b1.mylist) # prints 0 , as A.mylist is empty
b1.addToList()
print len(b1.mylist) # prints 1 , as we have added to A.mylist via addToList()
b2 = B()
print len(b2.mylist) # prints 1 !!! Why ?????
You need to do:
class A:
def __init__(self):
self.mylist=[]
That way self.mylist is an instance variable. If you define it outside of a method it is a class variable and so shared between all instances.
In B if you define a constructor you'll have to explicitly call A's constructor:
class B(A):
def __init__(self):
A.__init__(self)
This is explained (not very clearly) in the Python tutorial.
This code creates a shared mylist among all instances of A (or subclasses)
class A():
mylist=[]
What you want to do is:
class A():
def __init__(self):
self.mylist=[]
What you've probably seen is people who do:
class A():
somevariable = a
def doit(self):
self.somevariable = 5
This works because it creates a new "somevariable" attribute because you are doing an assignment. Before that all A instances share the same copy of somevariable. As long as you don't change the copy that is fine. When the variable is assigned to, then it gets replaced rather then modified. So that technique is only really safe when the values in question are immutable (i.e. you can't change them, you can only replace them) However, I think that's a really bad idea and you should always assign all variables in init

Categories