I have one base class constructor. from that i want to inherit into class method. But it showing the error like TypeError: __init__() missing 1 required positional argument: 'name'
Here is my code snippet.
class A:
def __init__(self,name):
self.name = name
def m1(self):
print(self.name)
class B(A):
#classmethod
def m2(cls):
super(B,cls).__init__(cls.m1)
b=B('siddarth')
b.m2 ()
Here it is another example. but without having any parameters in constructor it is working fine.
class A:
def __init__(self):
print('This is constructor method..!!')
class B(A):
#classmethod
def m2(cls):
super(B,cls).__init__(cls)
b=B('siddarth')
b.m2()
You can code it like this:
class A:
def __init__(self,name):
self.name = name
def m1(self):
print(self.name)
class B(A):
def __init__(self, cls):
super(B, self).__init__(cls)
b=B('siddarth')
b.m1()
OUTPUT
siddarth
Related
I have a very naïve question.
I have the following code in Python:
class A:
def __init__(self):
print("constructor A")
class B(A):
pass
ob = B()
It gives the following output:
constructor A
Similarly in the following code:
class A:
def __init__(self,name):
self.name = name
print(f'{self.name}')
class B(A):
def __init__(self):
print('Class B constructor')
ob1 = B()
ob2 = B('abc')
Shouldn't the output be:
class B constructor
abc
In fact it gives the following error:
TypeError: B.__init__() takes 1 positional argument but 2 were given
Isn't def __init__(self,name) of class A gets inherited in class B and can't we call it using ob2 = B('abc')?
Just to mention, __init__ is not constructor, it's initializer. It initializes the newly created object returned from __new__.
No, it Python attributes(including methods) of the classes are resolved using mro(Method Resolution Order), Whenever Python finds that, it stops going further.
In this example, Python didn't find fn in C, so it checks B, then A, and now it finds it. (If it didn't find it in A, it checks object class which is the last class in every class's MRO. In that case it raises AttributeError because object doesn't have fn either)
class A:
#staticmethod
def fn():
print("fn in A")
class B(A):
pass
class C(B):
pass
print(C.mro())
C.fn()
output:
[<class '__main__.C'>, <class '__main__.B'>, <class '__main__.A'>, <class 'object'>]
fn in A
If for example B has defined fn, it stops there:
class A:
#staticmethod
def fn():
print("fn in A")
class B(A):
#staticmethod
def fn():
print("fn in B")
class C(B):
pass
print(C.mro())
C.fn()
output:
[<class '__main__.C'>, <class '__main__.B'>, <class '__main__.A'>, <class 'object'>]
fn in B
Same thing happens to __init__.
If you want your code to work, you need to call the A's initializer inside the B's initializer. Note that the signature of the B's __init__ should compatible with the A's __init__. By compatible I mean it should take at least the number of parameters that A's __init__ takes, because you're going to pass those parameters to A.__init__:
class A:
def __init__(self, name):
print("Class A initializer")
self.name = name
print(f"{self.name}")
class B(A):
def __init__(self, name):
super().__init__(name)
print("Class B initializer")
ob2 = B("abc")
If you want the __init__() in A to be called, you have to do it yourself:
class A:
def __init__(self, name):
self.name = name
print(f'{self.name}')
class B(A):
def __init__(self, name):
print('Class B constructor')
super().__init__(name):
ob2 = B('abc')
Output
class B constructor
abc
You are trying to override constructor inside class B. class B inheritances from class A. And class A constructor except name argument. You don't need add init method inside B class here. One of the advantage using OOP is to reduces repetition. You decided to which parameters parent class will have. If you don't use parent class attributes in child class then there is no logic to create parent class. In short, parent class store attributes and methods in common, and if you want, you can add more attributes and method to child classes.
Code snippet will be like this
class A:
def __init__(self,name):
self.name = name
print(f'{self.name}')
class B(A):
def __init__(self,name):
super().__init__(name, ...) # here you can add attributes that is specific to B class
print('Class B constructor')
ob2 = B('abc')
class A:
def __init__(self, name):
self.name = name
print(f'{self.name}')
class B(A):
def __init__(self, *args):
if len(args) == 1:
super(B, self).__init__(name=args[0])
else:
print('Class B constructor')
ob1 = B()
ob2 = B('abc')
*args can control how many objects you enter, in that situation we can enter 1 or 0 objects.
if you enter 0 objects in your constructor, it will generate ('Class B constructor'), but if you enter 1 object, with super() method you call the A class constructor and name is equals to object, that is entered in the constructor.
it's because you __init__ take only one argument self which is always passed you need to add name to the definition of B
class A:
def __init__(self,name):
self.name = name
print(f'{self.name}')
class B(A):
def __init__(self, name):
print('Class B constructor')
ob2 = B('abc')
When I try to do this I get the error NameError: global name 'name' is not defined is there an easy work around?
class C(object):
def __init__(self, name):
self.name = name
class D(C):
def __init__(self):
C.__init__(self, name)
obj1 = D()
In class D, when you initialize it from C, you're not passing a value to the initialization of C, so it raises a NameError when it tries to pass it. You either need to allow D to take a value name and then pass it to C,
class C(object):
def __init__(self, name):
self.name = name
class D(C):
def __init__(self, name):
C.__init__(self, name) # name must be passed on initialization of D.
or define a default value for name in D.
class C(object):
def __init__(self, name):
self.name = name
class D(C):
def __init__(self, name='Monty Python'):
C.__init__(self, name) # allows you to only pass a name if you want to.
Instead of using the parent class name use super() here so that later if you need to you can enable things like mixins, interfaces, abstract classes, etc.
Then you can also allow for those keyword arguments in the parent class to be used in the child class like this:
class D(C):
def __init__(self,**kwargs):
super(D,self).__init__(**kwargs)
Example usage:
In [349]: obj1 = D(name='test')
In [350]: obj1.name
Out[350]: 'test'
never ever hard code the metho you inheriting instead of do super() by this if you want to change the method just change in the class name will be sufficient
there is no need to give argument's to super() in python3
class C(object):
def __init__(self, name):
self.name = name
class D(C):
def __init__(self, name):
super().__init__(self, name)
I have a parent class and several subclasses. Every subclass accepts different parameters, but all subclasses have some common parameters. I don't want to write the "common parameters" for every subclass. How can I do this?
class Parent:
def __init__(self, name):
self.name = name
class Subclass(Parent):
def __init__(self, age):
self.age = age
def do_something(self):
print(self.name)
instance = Subclass(name="Test", age=42)
instance.do_something() # 42
You can try this:
class Subclass(Parent):
def __init__(self, **kwargs):
super().__init__(kwargs['name'])
self.age = kwargs['age']
def do_something(self):
print(self.name)
And then use this just like you did in the question:
instance = Subclass(name="Test", age=42)
I use it in the following manner
You can add as many child classes as you want
class ParentClass(object):
def __init__(self,baseArgs):
self.var1=baseArgs['var1']
self.var2=baseArgs['var2']
self.var3=baseArgs['var3']
class ChildClass(ParentClass):
def __init__(self,childArgs,baseArgs):
super(ChildClass, self).__init__(baseArgs)
self.cvar1=childArgs['cvar1']
self.cvar2=childArgs['cvar2']
a=ChildClass({'cvar1':40,'cvar2':50},{'var1':10,'var2':20,'var3':30})
print(a.var1)
# 10
Is there any way to access parent class method, without actually calling the class?
e.g.:
1)
class A():
def __init__(self):
print('A class')
def name():
print('name from A class')
2)
class B(A):
# I want to make use of name without actually calling or running A.
# Is there any way to do that?
Yeah, you can just call it directly. This works fine:
class A():
def __init__(self):
print('A class')
def name(self):
print('name from A class')
class B(A):
pass
B().name()
> A class
> name from A class
You can also use it inside of the class, like
class B(A):
def b_name(self):
print('I am B!')
self.name()
If what you're trying to get around is calling A's init, then maybe you should turn name into a classmethod:
class A():
def __init__(self):
print('A class')
#classmethod
def name(self):
print('name from A class')
A.name()
> name from A class
Alternatively, you can give B an init which doesn't call its super class, thus instantiating it without calling A's init. I don't particularly recommend this method:
class A():
def __init__(self):
print('A class')
def name(self):
print('name from A class')
class B(A):
def __init__(self):
print('B class')
def b_name(self):
print('b_name from B class')
self.name()
B().b_name()
> B class
> b_name from B class
> name from A class
i am new to OOP.
i have a parent class with a method that i wanna access in my subclass. But i cannot figure out the right syntax for that. I cannot find a clear cut example anywhere
Members in the base class are simply available to the subclass as well (unless they are overwritten):
class Base:
def example (self):
print('This is in the base class')
class Subclass (Base):
def test (self):
self.example()
An object of type Subclass can now access example directly or indirectly:
>>> x = Subclass()
>>> x.test()
This is in the base class
>>> x.example()
This is in the base class
class Parent(object):
def __init__(self, name):
self.name = name
def output(self):
print self.name
class Child(Parent):
def __init__(self, name, age):
Parent.__init__(self, name)
self.age = age
def output(self):
super(Child, self).output()
print self.age
if __name__ == '__main__':
a = Parent("wy")
b = Child("zhang", 10)
a.output()
b.output()
You can try this code.