Python3 redefine a class: super still calls old class - python-3.x

This code:
class a:
def __init__(self):
print("a here")
class b(a):
def __init__(self):
print("b here")
super().__init__()
B = b()
class a:
def __init__(self):
print("NEW a here")
BB = b()
produces this output:
b here
a here
b here
a here
Why?
If I change the super().init() in class b to a.init(self), it works correctly.

Class b holds a reference to its base class(es). That reference is created when the class is created, not looked up by name later on when super gets called. Thus, the "incorrect" behavior that you're seeing is actually the expected behavior. To change what class b sees as its base class, you need to redefine b too.

I think that this is happening because class b is still inheriting from the original class a that you defined.
You can check this by printing out the ids of the a classes
id(a)
id(b.__bases__[0])

Related

Instantiate parent class only once when calling from two child classes

I would like to know if there's a way that we can instantiate a class only once when called from one of the child class and somehow cache it and use it for second child class without instantiating the parent class.
class A:
def __init__(self):
#some huge data stored in self parameters.
class B:
def __init__(self):
A.__init__(self)
class C:
def __init__(self):
A.__init(self)
So both classes B and C uses class A as a parent class and class A has huge data initialised which can be used by both classes B and C. So what I'm trying to achieve here is when I instantiate class B for example, it instantiates class A and loads all the data into memory and to cache the instance so when I immediately instantiate class C it looks for the existing instance of the class without instantiating it again.
How about instantiating A in B and providing a method to transfer the data from B to outside? See below:
class A:
def __init__(self):
self.huge_data = [.....]
def data(self):
return self.huge_data
class B:
def __init__(self):
self.a = A()
def pass_data(self)
return a.data()
class C:
def __init__(self):
A.__init(self)
Once you instantiate B, you will be able to use the method to access the data.

how to modify a variable value in a Python module using inheritance

I have a class A with many methods. There is one particular method that is referring to an external variable from the module imported. I don't have control of the module. In order to work around the problem I have created a class B that inherits from class A and modified the method by removing the reference to this external value. However, this a large method that might change. Is there a way to inherit the entire class but only modify the external value from the module?
external_value = 5
class A():
def add(self, b, c):
print(external_value)
print(b+c)
#100s of lines of code
class B(A):
def add(self, b,c):
print(b+c)
#100s of lines of code
a1 = A()
a1.add(3,5)
b1 = B()
b1.add(3,5)
You could use unittest.mock.patch for this:
external_module.py:
external_value = 5
class A:
def add(self, a, b):
print(external_value)
print(a + b)
your_module.py:
from unittest.mock import patch
from external_module import A
class B(A):
def add(self, *args, **kwargs):
with patch("external_module.external_value", 99):
return super().add(*args, **kwargs)
If you now instantiate B and call add, this happens:
>>> b = B()
>>> b.add(1, 2)
99
3

Python Multiple Inheritance - values not accessible

I have a few classes set up that hold values for an application. I'd like to import them into the same class, however, the values in the last class are being ignored. Here is a simple example.
class A:
def __init__(self):
self.testA = 'A'
class B:
def __init__(self):
self.testB = 'B'
class C(A, B):
def __init__(self):
super().__init__()
print(self.testA)
print(self.testB)
test = C()
The above will work only if I do not include the print(self.testB) the variable in class 'B'. I'd like to access the data from Class B as well. How? Thank you.

In python multiple inheritance without creating object for a class i'm able to get class variable

class A:
print('class A')
def __init__(self):
print('---1')
print('1')
class B:
print('class B')
def __init__(self):
print('sss')
class C(A,B):
print('222')
def __init__(self):
return 11
class D(B,A):
print('pp')
d1 = D()
I'm getting output:
class A
class B
222
pp
sss
Why 222 is getting print without creating an object for Class C.
Remove d1 = D() and you'll see that the first three lines are still printed.
This is because unlike function definitions, class definitions are not deferred until the class is constructed. The interpreter instead executes each line as it parses it.

Class inheritance python 3.6 : Similar methods

I'm not the strongest pillar when it comes to class inheritance, so here goes my rather silly question. Following the code below, I would logically assume that after the 'super' call, the pointer arrives at self.example() which would in turn refer to the 'example' method in the same class and value 20 will be printed.
class A(object):
def __init__():
self.example()
def example(self):
print(20)
class B(A):
def __init__():
super().__init__()
def example(self):
print(10)
x = B()
Result : 10
This clearly isn't the case and 10 is printed instead. Could someone please shed some light on the mysterious world of class inheritance.
class A(object):
def __init__():
self.example()
def example(self):
print(20)
class B(A):
def __init__():
super().__init__()
x = B()
x.example()
Look for this, at example.
When you inherit B, from A, then method example is inheritated to B, you not must rewrite this to B. Of course still you can write this method for B, then you will override 'A' method, for objects of class B.
You also can use one class to Inheritance with many others:
class Base(object):
def __init__(self):
print("Base created")
class ChildA(Base):
def __init__(self):
Base.__init__(self)
class ChildB(Base):
def __init__(self):
super(ChildB, self).__init__()
ChildA()
ChildB()
ChildB have another call which is equivalent to that used in example above.

Resources