I have two classes A and B, I want to run a method from class A in class B. I wrote the code but it's not working, I am getting the following error:
AttributeError: 'B' object has no attribute 'testPrint'
My classes:
class A:
def __init__(self):
self.v = 'A'
def test_1(self):
i = 1
print('Function test_1 in class A: ')
x = self.testPrint(i) # i think error is here
return x
def testPrint(self, i):
return 'testPrint: '+i
class B:
def __init__(self):
self.v = 'B'
def b1(self):
print('wywolanie funkcji z klasy b')
f = A.test_1(self)
return f
Run the program
b = B()
b.b1()
You need to instanciate class A:
class A:
def __init__(self):
self.v = 'A'
def test_1(self):
i = 1
print('Function test_1 in class A: ')
x = self.testPrint(i) # i think error is here
return x
def testPrint(self, i):
return 'testPrint: %s' % i
class B:
def __init__(self):
self.v = 'B'
def b1(self):
print('wywolanie funkcji z klasy b')
f = A().test_1()
return f
b = B()
res = b.b1()
print (res)
Returns (Python3):
wywolanie funkcji z klasy b
Function test_1 in class A:
testPrint:1
Related
I had meet the problem that, when calling method in class A, I need to set the value or call some functions in other classes, but I need all of them in the same python file, which is really long and ugly
. Are there some appropriate ways to write it clean?
Ideally, I hope this classes can be in seperate python file.
class A:
def __init__(self):
super(A, self).__init__()
self.value = 10
def set(self, new_value):
self.value = new_value
# set B value = new_value * 2
c.b.set(new_value * 2)
# set C value = new_value / 2
c.value = new_value / 2
class B:
def __init__(self):
super(B, self).__init__()
self.value = 10
def set(self, new_value):
self.value = new_value
class C:
def __init__(self):
super(C, self).__init__()
self.value = 1
self.a = A()
self.b = B()
if __name__ == '__main__':
c = C()
# class a function is called then class B and class C do somethings ...
c.a.set(100)
print(c.value)
print(c.a.value)
print(c.b.value)
There are many solutions to your design constraints, but here is one where dependencies are eliminated:
# imagine each of these classes are in their own projects (/A,/B,/C), in their own files (A.py, B.py, C.py)
class A:
def __init__(self, c):
self.value = 10
self.c = c
def set(self, new_value):
self.value = new_value
# set B value = new_value * 2
self.c.b.set(new_value * 2)
# set C value = new_value / 2
self.c.value = new_value / 2
# class B as before
class C:
def __init__(self, A, B):
self.value = 1
self.a = A()
self.b = B()
# Now main.py
from A.A import A
from B.B import B
from C.C import C
if __name__ == '__main__':
c = C(A, B) # Pass in the classes A and B which C will instantiate
# class a function is called then class B and class C do somethings ...
c.a.set(100)
print(c.value)
print(c.a.value)
print(c.b.value)
btw: A class which does not derive from another does not need to call super init.
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.
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
...
I would like to use functions based on strings passed in argument as below. The code gives the following error: AttributeError: 'Obj' object has no attribute 'funA'
The functions funA and funB are defined within fun because they are only used within fun and nowhere else
class Obj(object):
def __init__(self):
self.A = 2
self.B = 3
def fun(self, ar):
def funA(self):
print self.A
def funB(self):
x = self.B + 4
print self.B
for letter in ar:
name = 'fun' + letter
getattr(self, name)()
obj_instance = Obj()
obj_instance.fun(['A', 'B'])
As an alternative you can try the following code. It gives you the opportunity to check whether a function exists or not.
class Obj(object):
def __init__(self):
self.A = 2
self.B = 3
def fun(self, ar):
def funA():
print self.A
def funB():
x = self.B + 4
print self.B
print x
for letter in ar:
name = 'fun' + letter
if name in locals():
locals()[name]()
obj_instance = Obj()
obj_instance.fun(['A', 'B'])
I wouldn't recommend it, but if you really need it, then you can do it this way:
class Obj(object):
def __init__(self):
self.A = 2
self.B = 3
def fun(self, ar):
def funA(self):
print self.A
def funB(self):
x = self.B + 4
print self.B
for letter in ar:
name = 'fun' + letter + '()'
exec(name)
obj_instance=Obj()
obj_instance.fun(['A', 'B'])
exec() executes any string that you put in parentheses as if it was python code.
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