Different instances of A in B (Python) - python

In a situation like this b1 and b2 both have the same instanse of A.
class A:
def __init__(self):
self.var=1
class B:
a=A()
def __init__(self):
pass
b1=B()
b2=B()
b1.a.var=2 #changing "var" in b1 would also change it in b2
print(b2.a.var) # prints 2
What should i do to have 2 different instances of A in B?

With B defined as it is, its attribute a belongs to the class itself, not each individual instance. You would need to do something like this:
class B:
def __init__(self):
self.a = A()
to get separate instances of A for every B.

You were using what amounts to a static variable. Try this:
class A:
def __init__(self):
self.var = 1
class B:
def __init__(self):
self.a = A()

You need to initialize it on a per-instance basis instead of at the class level like you have now:
class B:
def __init__(self):
self.a = A()

You're initialising A() as a static class variable when it is first parsed.
To have one instance of A() per instance of B() it should be in the __init__ of B()
class A:
def __init__(self):
self.var=1
class B:
def __init__(self):
self.a = A()
b1=B()
b2=B()
b1.a.var=2 # changing "var" in b1 would not change it in b2
print(b2.a.var) # now prints 1

Related

Python - Subclass

How to call a subclass, for example, class1.class2.function, just like subdomains, shop.domain.com i tried this method
class A:
class B:
def ping():
print("Hi")
a = A()
b = a.B()
but it didn't work.
i also tried
class A:
def ping():
print("Class A")
class B(A):
def pingB():
print("Class B")
but also didn't work
You didn't add the self argument-
IN FIRST CASE:
class A:
class B:
def ping(self):
print("Hi")
a = A()
b = a.B()
b.ping()
IN SECOND CASE:
class A:
def ping():
print("Class A")
class B(A):
def pingB(self):
print("Class B")
b = B()
b.pingB()
Hope so this information is useful to you!
Happy Coding!
You still need to call the function within the B class when initializing b as the subclass B. Also, functions within a class need the self parameter.
class A:
class B:
def ping(self):
print("Hi")
a = A() # Initializing variable <a> as new object to class <A>
b = a.B() # Initializing variable <b> as new object to class <B> (Subclass of a)
b.ping() # Calling function <ping> which should print the string "Hi"

How to use #classmethod in python with inheritance [duplicate]

I would expect the following code to print 012345 but it prints 012012. Why? I would expect the calls to incr to be accessing the same variables since they are inherited from the same class but they are clearly different variables.
class a(object):
var = 0
#classmethod
def incr(cls):
print cls.var
cls.var+=1
class b(a):
def func(self):
super(b,self).incr()
class c(a):
def func(self):
super(c,self).incr()
t = a()
t1 = b()
t2 = c()
t1.func()
t1.func()
t1.func()
t2.func()
t2.func()
t2.func()
They are inherited from the same class, but the cls passed to the classmethod via super is the current class where the method was called from. super accesses the base class version of the method, but the cls for the call is the class where the super call was made.
This is one of the subtle differences between doing:
def func(self):
super(c, self).incr() # same as a.__dict__['incr'].__get__(self, type(self))()
and:
def func(self):
a.incr()
You can confirm this by printing the current cls in your incr method in both cases:
def incr(cls):
print cls
...
You should never assume that all super does is make a method call bound to the parent class. It does a lot more.
Keep in mind that when the first augmented assignment += is performed, the initial value of var is read from the base class (since at this point it does not exist in the dict of the subclasses). The updated value is however written to the subclass. Calling super from the second subclass repeats the same behavior of reading the initial var value from a.
There is a way to produce the sequence 012345. You have to make sure that the var of class a is increased in the incr method, even when it is called in the subclasses.
To achieve this, increment by a.var += 1, not by cls.var += 1.
As pointed out by the other answers, the var is also inherited to b and c.
By using cls.var += 1 both subclasses increase their own var instead of a's var.
class a:
var = 0
#classmethod
def incr(cls):
print(cls.var)
a.var += 1
class b(a):
def f(self):
super().incr()
class c(a):
def f(self):
super().incr()
cb = b()
cc = c()
cb.incr()
cb.incr()
cb.incr()
cc.incr()
cc.incr()
cc.incr()
cb.incr()
cc.incr()
Produces:
0
1
2
3
4
5
6
7
Both class b and class c inherit from class a separately, and var is set to 0 each time.
One way to have class c to get the same value of var in class a as class b does, class c can inherit from class b like so:
class a(object):
var = 0
#classmethod
def incr(cls):
print cls.var
cls.var+=1
class b(a):
def func(self):
super(b,self).incr()
class c(b):
def func(self):
super(c,self).incr()
t = a()
t1 = b()
t2 = c()
t1.func()
t1.func()
t1.func()
t2.func()
t2.func()
t2.func()`

python class methods and inheritance

I would expect the following code to print 012345 but it prints 012012. Why? I would expect the calls to incr to be accessing the same variables since they are inherited from the same class but they are clearly different variables.
class a(object):
var = 0
#classmethod
def incr(cls):
print cls.var
cls.var+=1
class b(a):
def func(self):
super(b,self).incr()
class c(a):
def func(self):
super(c,self).incr()
t = a()
t1 = b()
t2 = c()
t1.func()
t1.func()
t1.func()
t2.func()
t2.func()
t2.func()
They are inherited from the same class, but the cls passed to the classmethod via super is the current class where the method was called from. super accesses the base class version of the method, but the cls for the call is the class where the super call was made.
This is one of the subtle differences between doing:
def func(self):
super(c, self).incr() # same as a.__dict__['incr'].__get__(self, type(self))()
and:
def func(self):
a.incr()
You can confirm this by printing the current cls in your incr method in both cases:
def incr(cls):
print cls
...
You should never assume that all super does is make a method call bound to the parent class. It does a lot more.
Keep in mind that when the first augmented assignment += is performed, the initial value of var is read from the base class (since at this point it does not exist in the dict of the subclasses). The updated value is however written to the subclass. Calling super from the second subclass repeats the same behavior of reading the initial var value from a.
There is a way to produce the sequence 012345. You have to make sure that the var of class a is increased in the incr method, even when it is called in the subclasses.
To achieve this, increment by a.var += 1, not by cls.var += 1.
As pointed out by the other answers, the var is also inherited to b and c.
By using cls.var += 1 both subclasses increase their own var instead of a's var.
class a:
var = 0
#classmethod
def incr(cls):
print(cls.var)
a.var += 1
class b(a):
def f(self):
super().incr()
class c(a):
def f(self):
super().incr()
cb = b()
cc = c()
cb.incr()
cb.incr()
cb.incr()
cc.incr()
cc.incr()
cc.incr()
cb.incr()
cc.incr()
Produces:
0
1
2
3
4
5
6
7
Both class b and class c inherit from class a separately, and var is set to 0 each time.
One way to have class c to get the same value of var in class a as class b does, class c can inherit from class b like so:
class a(object):
var = 0
#classmethod
def incr(cls):
print cls.var
cls.var+=1
class b(a):
def func(self):
super(b,self).incr()
class c(b):
def func(self):
super(c,self).incr()
t = a()
t1 = b()
t2 = c()
t1.func()
t1.func()
t1.func()
t2.func()
t2.func()
t2.func()`

One constant value for multiple classes

Let's say that I have six different classes and three of them should use the same constant value. What can we do? We either:
Define as global variable
A = 1
class B:
def __init__(self):
self.a = A
class C:
def __init__(self):
self.a = A
class D:
def __init__(self):
self.a = A
Define as class level for 1 class and give it to another class:
class B:
A = 1
def __init__(self):
self.b = 2
class C:
def __init__(self, a):
self.a = a
self.b = 3
b = B()
c = B(a=b.A)
The second way I just made up and as for me it's dirty and not convenient. Is there any way to avoid using a global variable?
Use class inheritance:
class Holder:
a = 4
class A(Holder):
pass
print A().a
You could use inheritance, using B as the base class
class B:
A = 1
def __init__(self):
self.b = 2
class C(B):
def __init__(self):
B.__init__(self)
self.a = B.A
self.b = 3
b = B()
c = C()
print c.a

Casting to other class in Python

I have a code (simplified):
class A(object):
attrib1 = "a"
attrib2 = "b"
class B(A):
flag = True
in some place in my code, I have an instance of A, but I need to create an instance of class B, which will have all the data from instance of A... I feel myself stupid, but I don't want to do something like:
class B(A):
def __init__(self,a1,a2,a3,a4,..):
self.a1 = a1
self.a2 = a2
and call like:
obj_b = B( obj_a.a1, obj_a.a2,...)
class B(A):
def __init__(self, obj):
self.__dict__.update(obj.__dict__)
Another option is to change the __class__ variable on your instance of A.
a = A()
a.__class__ = B

Categories

Resources