How to instantiate multiple classes in one class: Python OOP - python

I've written a code with 3 different classes - those classes initializes functions and connected between each other (class B calls function a_calc() from A class; class C calls function b_calc() from B class). I want to create Calculator() function that instantiates all of those classes (A, B, C), uses class functions in one line of code, and returns the result of execution (to be able to execute the program creating only one object Main). Here the snippet of code (simplified):
class A(object):
def __init__(self):
self.a = 10
def a_calc(self):
a = self.a + 1
return a
class B(object):
def __init__(self, A):
self.A = A
def b_calc(self):
b = self.A.a_calc() + 2
return b
class C(object):
def __init__(self, B):
self.B = B
def c_calc(self):
c = self.B().b_calc + 3
return c
class Calculator(A, B, C):
def __init__(self):
result = A.a_calc() + B.b_calc() + C.c_calc()
print(result)
calc = Calculator()
Yet, I'm getting an error:
Traceback (most recent call last):
File "/home/taras/PycharmProjects/ResSysPymage/test#2.py", line 31, in <module>
calc = Calculator()
File "/home/taras/PycharmProjects/ResSysPymage/test#2.py", line 27, in __init__
result = A.a_calc() + B.b_calc() + C.c_calc()
TypeError: a_calc() missing 1 required positional argument: 'self'
How can I make my idea come true? I'd be grateful for ideas:)

You seem to be confusing classes, instances of classes and composition vs. multiple inheritance.
Perhaps you're looking for something like this:
class A:
def __init__(self):
self.a = 10
def a_calc(self):
a = self.a + 1
return a
class B:
def __init__(self, a: A):
self.a = a
def b_calc(self):
b = self.a.a_calc() + 2
return b
class C:
def __init__(self, b: B):
self.b = b
def c_calc(self):
c = self.b.b_calc() + 3
return c
def calculator():
a = A()
b = B(a)
c = C(b)
return a.a_calc() + b.b_calc() + c.c_calc()
print(calculator())

Related

using __new__ to return object from different classes depending on input

I wanted to override __new__ function, for a specific class, in such a way that depending on the input passed, it returns an object from a class or from another.
I wrote the following code - which seems to work - but it feels like cheating and I wanted to know if this is the "best" or the "most python-like" way to do:
class A:
def __new__(cls, x):
if x == 1:
a = 0
self = B.__new__(A, a)
self.cls = B
else:
a = 0
b = 0
self = C.__new__(A, a, b)
self.cls = C
return self
def __init__(self, x):
self.__class__ = self.cls
class B(A):
def __new__(cls, a):
self = object.__new__(cls)
self.a = a
return self
def print_this(self):
print("self.a is: ", self.a)
print("class is B")
class C(A):
def __new__(cls, a, b):
self = object.__new__(cls)
self.a = a
self.b = b
return self
def print_this(self):
print("self.a is: ", self.a)
print("self.b is: ", self.b)
print("class is C")
xxx = A(1)
print("xxx.__class__: ", xxx.__class__)
xxx.print_this()
yyy = A(2)
print("yyy.__class__: ", yyy.__class__)
yyy.print_this()
it returns the following, which is what I wanted
xxx.__class__: <class '__main__.B'>
self.a is: 0
class is B
yyy.__class__: <class '__main__.C'>
self.a is: 0
self.b is: 0
class is C
Yes, it's dirty - it's not obvious for a reader that A() actually creates instance of another class, if someone change something in B.__new__ he can break parts he would never expects and could be hard to understand for non-experienced python programmers what is going on here.
What you search for is factory design pattern.
from enum import Enum
class ClsEnum(Enum):
B = "B"
C = "C"
class A:
pass
def cls_factory(e: ClsEnum) -> A:
if e == ClsEnum.B:
return B(0)
elif e == ClsEnum.C:
return C(0, 0)
raise TypeError
class B(A):
def __init__(self, a):
self.a = a
def print_this(self):
print("self.a is: ", self.a)
print("class is B")
class C(A):
def __init__(self, a, b):
self.a = a
self.b = b
def print_this(self):
print("self.a is: ", self.a)
print("self.b is: ", self.b)
print("class is C")
xxx = cls_factory(ClsEnum.B)
print("xxx.__class__: ", xxx.__class__)
xxx.print_this()
yyy = cls_factory(ClsEnum.C)
print("yyy.__class__: ", yyy.__class__)
yyy.print_this()
This code gives the same output as your version.

Variables defined in __init__ appearing as "not defined" when I use them in other functions

I am currently using classes with functions inside, and in this example, I have defined a class with some variables inside:
class Thing():
def __init__(self, a, b, c):
self.a = a
self.b = b
self.c = c
def func(d):
return a - b - c + d
However, whenever I run:
>>> t = Thing(30, 6, 7)
>>> t.func(4)
Traceback (most recent call last):
File "<pyshell#35>", line 1, in <module>
t.func(4)
File "---", line 7, in func
print(a - b - c + d)
NameError: name 'a' is not defined
How do I fix this??
You wrongly referenced your a, b, c variables in your func method.
Try this:
class Thing():
def __init__(self, a, b, c):
self.a = a
self.b = b
self.c = c
def func(self, d):
return self.a - self.b - self.c + d

How do i inherit 2 values from method in python

class a():
def __init__(self):
print("hello")
def add(self,a,b):
print("c = {}".format(self.a+self.b))
class b(a):
def __init__(self):
a.__init__(self)
h = b()
h.add(2,3)
please tell me my error code not working
Error Traceback (most recent call last): File "Inheritance.py", line 10, in
h.add(2,3) File "Inheritance.py", line 5, in add
print("c = {}".format(self.a+self.b)) AttributeError: 'b' object has no attribute 'a'
When you define class B define it as class B(A) and it will have inherit everything from class A, also take note that whatever you have inside def _init_(self) will be executed when the instance is created.
*Using f-strings to print, valid for python3.6+, if not you may use your original print method
class A():
def __init__(self):
print("hello")
def add(self, a, b):
print(f"c = {a + b}")
class B(A):
pass
h = B()
h.add(2,3)
Output:
(xenial)vash#localhost:~/python/stack_overflow$ python3.7 inherit.py
hello c = 5
If you would like to create variables h.a and h.b you would want to take this route:
class A():
def __init__(self, a, b):
print("hello")
self.a = a
self.b = b
def add(self):
print(f"c = {self.a + self.b}")
class B(A):
pass
h = B(2, 3)
print(h.a)
print(h.b)
h.add()
Output:
(xenial)vash#localhost:~/python/stack_overflow$ python3.7 inherit.py
hello
2
3
c = 5

Troubles managing attributes in python's class

I am a python beginner and it is my first time dealing with OOP. Could you help me to figure out what I am doing wrong whit the code below:
class Example(object):
def __init__(self, a, b):
self.a = a
self.b = b
self.c = self.a + self.b/2
def property1(self):
self.obs1 = self.a - self.c
def property2(self):
self.obs2 = self.b - self.c
def get_obs1(self):
return self.obs1
def get_obs2(self):
return self.obs2
test = Example(2,5)
test.get_obs1()
I obtain the following exceptions:
Traceback (most recent call last):
File "/home/panadestein/Programming_Games/Python/buggy.py", line 22, in <module>
test.get_obs1()
File "/home/panadestein/Programming_Games/Python/buggy.py", line 16, in get_obs1
return self.obs1
AttributeError: 'Example' object has no attribute 'obs1'
As at when get_obs1 was called the attribute obs1 was not yet defined and not yet bounded to your class instance. Your question already gives a hint at using property, so use this instead and define your private variables in __init__:
class Example(object):
def __init__(self, a, b):
self.a = a
self.b = b
self.c = self.a + self.b/2
self._obs1 = self.a - self.c
self._obs2 = self.b - self.c
#property
def obs1(self):
return self._obs1
#property
def obs2(self):
return self._obs2
test = Example(2,5)
test.obs1
Read more on #property

How to create a simple function within a class in Python?

I am starting to work with classes in Python, and am learning how to create functions within classes. Does anyone have any tips on this sample class & function that I am testing out?
class test:
def __init__(self):
self.a = None
self.b = None
self.c = None
def prod(self):
return self.a * self.b
trial = test
trial.a = 4
trial.b = 5
print trial.prod
Ideally the result would be to see the number 20.
You need to:
Create an instance of test.
Invoke the prod method of that instance.
Both of these can be accomplished by adding () after their names:
trial = test()
trial.a = 4
trial.b = 5
print trial.prod()
Below is a demonstration:
>>> class test:
... def __init__(self):
... self.a = None
... self.b = None
... self.c = None
... def prod(self):
... return self.a * self.b
...
>>> trial = test()
>>> trial.a = 4
>>> trial.b = 5
>>> print trial.prod()
20
>>>
Without the parenthesis, this line:
trial = test
is simply assigning the variable trial to class test itself, not an instance of it. Moreover, this line:
print trial.prod
is just printing the string representation of test.prod, not the value returned by invoking it.
Here is a reference on Python classes and OOP.
Ideally you could also pass in the values to a, b, c as parameters to your object's constructor:
class test:
def __init__(self, a, b, c):
self.a = a
self.b = b
self.c = c
def prod(self):
return self.a * self.b
Then, constructing and calling the function would look like this:
trial = test(4, 5, None)
print trial.prod()

Categories