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
Related
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.
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())
I have a class A encapsulating a class B instance and additional stuff. The following is a toy example.
class B(object):
def __init__(self):
self.b = 2
def square(self):
return self.b * self.b
class A(object):
def __init__(self, x):
self.b = B()
a = A(1)
print(a.b.square())
Any time an A instance wants to call a method in B, I always need to do things like 'a.b'. My hope is to get rid of '.b' for user convenience. The following codes do the job.
class B(object):
def __init__(self):
self.b = 2
def square(self):
return self.b * self.b
class A(object):
def __init__(self, x):
self.b = B()
def square(self):
return self.b.square()
a = A(1)
print(a.square())
The problem is that class B is from outside library and there are lots of and different types of things in the dir. I couldn't do it one by one manually like above. Any magical ways to handle that?
Any magical ways to handle that?
It's python, of course there are! You can use __getattr__ function to proxy unknown calls to b:
class B(object):
def shadowed(self):
print('B.shadowed')
def unshadowed(self):
print('B.unshadowed')
class A(object):
def __init__(self):
self._b = B()
def shadowed(self):
print('A.shadowed')
def __getattr__(self, name):
return getattr(self._b, name)
test = A()
test.shadowed()
test.unshadowed()
test.unknown()
Result:
A.shadowed
B.unshadowed
Traceback (most recent call last):
File "/Users/Andrew/Desktop/test.py", line 23, in <module>
test.unknown()
File "/Users/Andrew/Desktop/test.py", line 17, in __getattr__
return getattr(self._b, name)
AttributeError: 'B' object has no attribute 'unknown'
__getattr__ is called when the object doesn't have attribute that's being asked for.
Getting below Attribute error while running below code. Class member function is accessed using self still it is giving error.
class A:
def __init__(self):
self.a=1
def f1(self):
self.b=2
def f2(self):
self.c=3
print(self.a,self.b,self.c)
self.f2()
model = A()
model.f1()
Error:
AttributeError: 'A' object has no attribute 'f2'
A does not have an attribute f2, but it does have an attribute f1 that calls a function f2. f2 is not an instance attribute.
In this case c is no longer an instance attribute, or data attribute, it is now just a local variable. This may or may not be what you were
going for.
class D:
def __init__(self):
self.a = 1
def f1(self):
# Instance attribute declared outside of __init__
self.b = 2
def f2():
c = 3
print(self.a, self.b, c)
f2()
Depending on your development environment you may or may not get a warning about instance attributes being declare outside of the __init__ function. It isn't necessary that you declare them this way, however, it improves readability.
class B:
def __init__(self):
self.a = 1
self.b = 2
self.c = 3
def f1(self):
def f2():
print(self.a, self.b, self.c)
f2()
This next block is slightly more explicit in what it says about the intent of the code.
class A:
def __init__(self):
self.a = 1
self.b = 2
self.c = 3
def f1(self):
def f2():
return '{} {} {}'.format(self.a, self.b, self.c)
return f2()
Perhaps you want f2() to be called using method attributes of the
self argument in which case:
class A2:
def __init__(self):
self.a = 1
self.b = 2
self.c = 3
def f2(self):
print(self.a, self.b, self.c)
def f1(self):
"""Do something that requires calling the self.f2()
print function.
"""
self.f2()
You do not need self when calling the nested function and nor does it need to be contained in the function signature:
class A:
def __init__(self):
self.a=1
def f1(self):
self.b=2
def f2():
c=3
print(self.a,self.b, c)
f2()
model = A()
model.f1()
Output:
1, 2, 3
Its not clear to me that you actually need to define a function within a method just to call it.
So, your code could just as easily be this:
class A:
def __init__(self):
self.a = 1
def f1(self):
self.b = 2
self.f2()
def f2(self):
self.c = 3
print(self.a, self.b, self.c)
model = A()
model.f1()
Output:
1 2 3
My code:
class A():
def __init__(self, a = 100):
self.a = a
class B():
def __init__(self, b = 200):
self.b = b
class C(A,B):
def __init__(self, a, b, c = 300):
super().__init__(a)
super().__init__(b)
self.c = c
def output(self):
print(self.a)
print(self.b)
print(self.c)
def main():
c = C(1,2,3)`enter code here`
c.output()
main()
Error:
2
Traceback (most recent call last):
File "inheritance.py", line 25, in <module>
main()
File "inheritance.py", line 23, in main
c.output()
File "inheritance.py", line 17, in output
print(self.b)
AttributeError: 'C' object has no attribute 'b'
Why it cannot inheritance the b?
what's wrong with this code???
And how to modify this code?
If I replace the supper() with A. or B. , it can run normally.
So what cause this problem?
If I do not use super(), what method can I use?
Inherit from object + fixed your "super" call
class A(object):
def __init__(self, a = 100):
self.a = a
class B(object):
def __init__(self, b = 200):
self.b = b
class C(A,B):
def __init__(self, a, b, c = 300):
A.__init__(self, a=a)
B.__init__(self, b=b)
self.c = c
def output(self):
print(self.a)
print(self.b)
print(self.c)