Override and extend method defined in parent class in Python - python

I want to redefine the method Old.do(self) in New.do(self, x) so that it takes one argument as below:
#!/usr/bin/env python3
class Old(object):
def __init__(self):
self.a = 0
self.do()
def do(self):
print(self.a)
class New(Old):
def __init__(self):
Old.__init__(self)
b = 1
self.do(b)
def do(self, b):
print(self.a + b)
if __name__ == '__main__':
new = New()
I can do it with the name mangling:
#!/usr/bin/env python3
class Old(object):
def __init__(self):
self.a = 0
self.__do()
def do(self):
print(self.a)
__do = do
class New(Old):
def __init__(self):
Old.__init__(self)
b = 1
self.do(b)
def do(self, b):
print(self.a + b)
if __name__ == '__main__':
new = New()
or I can do it with an explicit reference to the base class:
#!/usr/bin/env python3
class Old(object):
def __init__(self):
self.a = 0
Old.do(self)
def do(self):
print(self.a)
class New(Old):
def __init__(self):
Old.__init__(self)
b = 1
self.do(b)
def do(self, b):
print(self.a + b)
if __name__ == '__main__':
new = New()
Is there any other way to get the same result? Can super() do this?
Thanks

You can do what you trying with super, like this:
class Old(object):
def __init__(self):
self.a = 1
Old.do(self, self.a)
def do(self, a):
print(a)
class New(Old):
def __init__(self):
super(New, self).__init__()
self.b = 2
self.do(self.b)
def do(self, b):
print(self.a + b)
new = New()
the first call will return 1, and the second call 3

Related

Using a variable from one class to another one in python

I want to use a variable from class A for some computation in class B. I,m not sure that I use the self.out from the class A in class B appropriately?
Class A:
class A(nn.Module):
def __init__(self):
super(A, self).__init__()
self.out = func()
Class B:
class B(nn.Module):
def __init__(self):
super(A, self).__init__()
self.result = function_1() + A.self.out
Maybe this is what you need. I made a small example of what I understood.
These "prints" were placed to improve the understanding that Class "C" can fetch any function or variable from the other parent classes.
class A():
def __init__(self):
variable = None
def test(self, number):
return f'another class {number}'
class B():
def __init__(self):
self.data = None
self.out = self.print_data(5)
def print_data(self, number):
return number
def print_elem(self):
return self.data
class C(A, B):
def __init__(self):
super().__init__()
c = C()
print(c.print_data(8))
print(c.out)
c.data = 100
print(c.print_elem())
print(c.test(3))

How can i do inheritance with three levels (father, child, grandchild)

I have the under
from abc import ABCMeta, abstractmethod
class Operation(object):
__metaclass__ = ABCMeta
def __init__(self, a, use_sftp):
print "OPERATION"
self.a = a
self.use_sftp = use_sftp
self.y = 5
#abstractmethod
def execute(self):
pass
class OperationExecutor(object):
def __init__(self, a, use_sftp):
print "EXECUTOR"
self.a = a
self.use_sftp = use_sftp
def batatas(self, operation):
op = operation(self.a, self.use_sftp)
return op.execute()
class FTP(Operation):
__metaclass__ = ABCMeta
def __init__(self, a, use_sftp):
print "FTP"
self.op = super(FTP, self).__init__(a, use_sftp)
self.b = 2
self.c = 3
self.x = 10
def execute(self):
if self.use_sftp:
return SFTP(self.a, self.use_sftp).execute()
else:
return LFTP(self.a, self.use_sftp).execute()
class SFTP(FTP):
def execute(self):
return self.a + self.b + self.c + self.x + self.y
class LFTP(FTP):
def execute(self):
return self.a * self.b * self.c * self.x * self.y
def main():
executor = OperationExecutor(1, True)
print executor.batatas(FTP)
if __name__ == '__main__':
main()
i want to run in the following order:
EXECUTOR,
FTP,
OPERATION
or similar, but i have the following:
EXECUTOR,
FTP,
OPERATION,
FTP,
OPERATION
This is because "init" is called twice. I don't want the "init" to be run more than once
Operation (father) ---> FTP (child) ---> SFTP/LFTP (grandchild)

Communication between class in Python

I can call a class from another class but not vice versa.
From class A (see below), I can call Method_B located in class B but from class B, I am not able to call Method_A1 or Method_A2 located in class A.
I got the following error:
NameError: name 'A' is not defined
Here is my code:
test_1.py:
from test_2 import *
class A():
def __init__(self):
self.key = 1
self.call_Method_B = B().Method_B(self.key)
def Method_A1(self):
print("Method_A1: ok")
def Method_A2(self):
print("Method_A2: ok")
if __name__ == '__main__':
start_A = A()
test_2.py:
class B():
def Method_B(self,key):
self.key = key
if self.key ==1:
self.call_Method_A1 = A().Method_A1()
else:
self.call_Method_A2 = A().Method_A2()
To communicate between scripts you need to import test_1 as a module:
from test_1 import *
and change the way you call A to like this:
if self.key ==1:
self.call_Method_A1 = A.Method_A1(self)
else:
self.call_Method_A2 = A.Method_A2(self)
You can pass class A as an argument when calling Method_B
test_1.py:
from test_2 import *
class A():
def __init__(self):
self.key = 1
self.call_Method_B = B().Method_B(self.key, A)
...
test_2.py:
class B():
def Method_B(self, key, A):
...
A more conventional way of showing this would be:
# test_1.py
from test_2 import B
class A():
def __init__(self):
self.key = 1
self.b = B(self)
self.b.method_b(self.key)
#staticmethod
def method_a1():
print("Method_A1: ok")
#staticmethod
def method_a2():
print("Method_A2: ok")
if __name__ == '__main__':
start_a = A()
# test_2.py
class B():
def __init__(self, instance_of_a):
self.a = instance_of_a
def method_b(self, key):
self.key = key
if self.key == 1:
self.a.method_a1()
else:
self.a.method_a2()
You have a loop in your imports. Try adding an import like this:
class B():
def Method_B(self,key):
from test_1 import A
....
This will then only import A from test_1 after it is defined.

Python: is it possible to link two variable belonging to two different classes?

I would like to connect two variables totwo different classes but I don't know if what I'm trying to do is possible or not.
for instance, if I have those two classes:
class one():
def __init__(self):
self.a = 0
def compute(self):
self.a = self.a + 1
class two():
def __init__(self):
self.a = 0
self.C_one = one()
self.link()
def link(self):
self.a = self.C_one.a
def compute(self):
self.C_one.compute()
print('C_one a=',self.C_one.a )
print('C_two a=',self.a )
C_two = two()
for i in range(5):
C_two.compute()
In the class two I would like connect the variable a with the variable a of class one, so I don't have to explicitly call self.a = self.C_one.a each time I execute C_two.compute
The code in example give me this:
C_one a= 1
C_two a= 0
C_one a= 2
C_two a= 0
C_one a= 3
C_two a= 0
C_one a= 4
C_two a= 0
C_one a= 5
C_two a= 0
Which is not the result I expect.
Somebody know if I can do that in python?
update
From the example below
class one():
def __init__(self):
self.a = 0
def compute(self):
self.a = self.a + 1
class two():
def __init__(self):
self.a = 0
class three():
def __init__(self):
self.C_one = one()
self.C_two = two()
self.b = 0
def compute(self):
self.C_one.compute()
#self.C_two.a = self.C_one.a
print('C_one a=',self.C_one.a )
print('C_two a=',self.C_two.a )
C_three = three()
for i in range(5):
C_three.compute()
is it possible to use the answer of deceze and replace the commented line #self.C_two.a = self.C_one.awith a property ? Like that classes one and two are linked in the class three.
answer from deceze
class one():
def __init__(self):
self.a = 0
def compute(self):
self.a = self.a + 1
class two():
def __init__(self,one):
self.C_one = one
#property
def a(self):
return self.C_one.a
class three():
def __init__(self):
self.C_one = one()
self.C_two = two(self.C_one)
self.b = 0
def compute(self):
self.C_one.compute()
print('C_one a=',self.C_one.a )
print('C_two a=',self.C_two.a )
C_three = three()
for i in range(5):
C_three.compute()
Define two.a as a property:
class two:
def __init__(self):
self.C_one = one()
#property
def a(self):
return self.C_one.a
...

Accidentally calling an ovverriden method from base class's __init__

This program seems to do everything by the book, yet this issue cropped up: while a base class was being init'ed a member method was called that is overriden in the derived class and assumes that the derived class has been constructed.
Is there some best practice to protect against this?
#!/usr/bin/env python3
class A:
def __init__(self):
self.ax = 1
print(self)
def __repr__(self):
return "{} ax: {}".format(self.__class__.__name__, self.ax)
class B(A):
def __init__(self):
super().__init__()
self.bx = 10
def __repr__(self):
return super().__repr__() + " bx: {}".format(self.bx)
if __name__ == "__main__":
B()
And here's the error:
AttributeError: 'B' object has no attribute 'bx'
Generally, unless you really know what you are doing, you want to call the superclass initialization after everything your class needs to do is done. Same with this example, repr is trying to print self.bx before you initialize it. If you do
class B(A):
def __init__(self):
self.bx = 10
super().__init__()
def __repr__(self):
return super().__repr__() + " bx: {}".format(self.bx)
it works as expected
Edited:
Instead of doing computation on __init__, one idea may be to do that in a factory function/classmethod.
Example instead of doing:
class A:
def __init__(self, a, b):
self.a = a
self.b = b
self.initialize()
def initialize(self):
# do some things
Do:
class A:
def __init__(self, a, b):
self.a = a
self.b = b
#classmethod
def from_a_b(cls, a, b):
instance = cls(a, b)
instance.initialize()
return instance

Categories

Resources