I'm having problem using super command
class s:
def __init__(self,a):
self.a=a
def show(self):
print self.a
class t:
def __init__(self,b):
self.b=b
def show2(self):
print self.b
class w(s):
def __init__(self,a,b,c):
super(w,self).__init__()
self.b=b
self.c=c
def show3(self):
super(w,self).show()
print self.b
print self.c
whenever i make an object it gives the following error
x=w(1,2,3)
Traceback (most recent call last):
File "<pyshell#0>", line 1, in <module>
x=w(1,2,3)
File "C:\Users\GURSAHEJ\Desktop\k.py", line 13, in __init__
super(w,self).__init__()
TypeError: must be type, not classobj
The super function will Return a proxy object that delegates method calls to a parent or sibling class of type so when you want to use it you need to pass the parent name to it,and since here your w class inherit from s you might want to pass s to super:
class w(s):
def __init__(self,a,b,c):
super(s,self).__init__()
self.b=b
self.c=c
Also don't forget to pass the object to your parent class to make it a new style class :
class s(object):
def __init__(self,a):
self.a=a
def show(self):
print self.a
Read about new style and classic classes it in python documentation https://docs.python.org/2/reference/datamodel.html#new-style-and-classic-classes
Because you are using super on an old-style class
In Python 2.x (>= 2.2), there are two type of classes. Old style classes and new-style classes. In python 3.x, old-style classes are removed and all classes are new-style class.
Python's build-in function super works properly on new-style classes.
Simply, new-style classes extends object while old style classes not.
Old Sytle Class
class s:
def __init__(self,a):
self.a=a
New Style Class
class s(object):
def __init__(self,a):
self.a=a
So, your classes which is not inherited from another class should be inherited from object to be a new style class.
You can either use new-style or use old-skool inheritance __init__
class w(s):
def __init__(self,a,b,c):
s.__init__(self, a)
This is an example of old-style solution, but I do not flag this question as a duplicate because new-style class usage is encouraged and you should avoid using old-style classes.
Related
I have written the follow code to demonstrate abstract methods that must be implemented by its subclasses. I read that when a method in a parent class is decorated as abstract, its subclass must implement it otherwise it cannot be instantiated. However, in the following code, the 'Slug' subclass does not implement the abstract method, yet it can still instantiate without errors being thrown. I thought in this case Python will complain?
Have I misunderstood something?
Thanks
import abc
class Animal(object):
__metaclass__ = abc.ABCMeta
def __init__(self, species):
self._species=species
def get_species(self):
return self._species
#abc.abstractmethod
def eat(self):
pass
class Slug(Animal):
def __init(self, species):
super(species)
def run(self):
print("running")
# def eat(self):
# pass
sl = Slug("slug")
print(sl.get_species())
no, you understood perfectly well! it is just that the python 3 syntax for abc.ABCMeta is:
class Animal(metaclass=abc.ABCMeta):
...
instead of __metaclass__ = abc.ABCMeta which was used in python 2. alternatively you can just inherit from ABC: class Animal(abc.ABC):. see doc.
and then:
class Slug(Animal):
def __init(self, species):
super.__init__(species)
...
this will result in
Traceback (most recent call last):
File "/home/.../...py", line 33, in <module>
sl = Slug("slug")
TypeError: Can't instantiate abstract class Slug with abstract methods eat
I have written this code in python 3.4 and used classes. I have implemented multiple inheritance in this code with super() function. And i want to call the init() function of library class. But i am unable, can anyone tell me the mistake?
code
class college:
def __init__(self, rollno):
print("Roll no:", rollno)
class library:
def __init__(self, libcardno):
print("Library card no:", libcardno)
class student(college, library):
def __init__(self, name):
print("Name:", name)
super().__init__(5560)
super().__init__(60)
output
>>> obj = student("John")
Name: John
Roll no: 5560
Roll no: 60
Just understand the question, it's not a duplicate of another one.
You can directly call __init__ method of respective parent class.
class student(college, library):
def __init__(self, name):
print("Name:", name)
college.__init__(self,5560)
library.__init__(self,60)
Short:
You can't and you don't need to use super() to call __init__ with different form. Of course there is a way to do, but I do not recommend that.
Long:
Python uses the list of classes to inherit from. You can see that list with
ClassName.__mro__. mro stands for Method Resolution Order
Think about you have three classes, ClassA, ClassB, ClassC and ClassC extends ClassA, and ClassB (If you are using python2, ClassA and ClassB musts extend from object)
class ClassC(ClassA, ClassB):
Then, ClassC.__mro__ will be like below:
(<class '__main__.ClassC'>, <class '__main__.ClassA'>, <class '__main__.ClassB'>, <class 'object'>)
So python inherits ClassC, ClassA, ClassB order. And it assumes that methods have same form in this list. This is why you can't use different forms of __init__ call using super().
If you need to use super() and there is no option, you can consider passing argument as **kwargs.
class ClassA():
def __init__(self, **kwargs):
super(ClassA, self).__init__(**kwargs)
print("Class A Initialized:", kwargs['a'])
class ClassB():
def __init__(self, **kwargs):
# super(ClassA, self).__init__(**kwargs)
# if you call above, you'll get type error, because above will call object.__init__ which takes only 1 argument
print("Class B Initialized:", kwargs['b'])
class ClassC(ClassA, ClassB):
def __init__(self, **kwargs):
super(ClassC, self).__init__(**kwargs)
print("Class C Initialized:", kwargs['c'])
ClassC(a="A", b="B", c="C")
And you can get below output :
Class B Initialized: B
Class A Initialized: A
Class C Initialized: C
But still, I recommend that do not use this form of inheritance, because it is very complicated
I'm trying to inherit attributes from a super class but they are not being initialized correctly:
class Thing(object):
def __init__(self):
self.attribute1 = "attribute1"
class OtherThing(Thing):
def __init__(self):
super(Thing, self).__init__()
print self.attribute1
This throws an error since attribute1 is not an attribute of OtherThing, even though Thing.attribute1 exists. I thought this was the correct way to inherit and extend a super class. Am I doing something wrong? I don't want to create an instance of Thing and use its attributes, I need it to inherit this for simplicity.
You have to give, as argument, the class name (where it is being called) to super():
super(OtherThing, self).__init__()
According to Python docs:
... super can be used to refer to parent classes without naming them
explicitly, thus making the code more maintainable.
so you are not supposed to give the parent class.
See this example from Python docs too:
class C(B):
def method(self, arg):
super(C, self).method(arg)
Python3 makes this easy:
#!/usr/local/cpython-3.3/bin/python
class Thing(object):
def __init__(self):
self.attribute1 = "attribute1"
class OtherThing(Thing):
def __init__(self):
#super(Thing, self).__init__()
super().__init__()
print(self.attribute1)
def main():
otherthing = OtherThing()
main()
I'd like to automatically run some code upon class creation that can call other class methods. I have not found a way of doing so from within the class declaration itself and end up creating a #classmethod called __clsinit__ and call it from the defining scope immediately after the class declaration. Is there a method I can define such that it will get automatically called after the class object is created?
You can do this with a metaclass or a class decorator.
A class decorator (since 2.6) is probably easier to understand:
def call_clsinit(cls):
cls._clsinit()
return cls
#call_clsinit
class MyClass:
#classmethod
def _clsinit(cls):
print "MyClass._clsinit()"
Metaclasses are more powerful; they can call code and modify the ingredients of the class before it is created as well as afterwards (also, they can be inherited):
def call_clsinit(*args, **kwargs):
cls = type(*args, **kwargs)
cls._clsinit()
return cls;
class MyClass(object):
__metaclass__ = call_clsinit
#classmethod
def _clsinit(cls):
print "MyClass._clsinit()"
I have the following kind of superclass / subclass setup:
class SuperClass(object):
def __init__(self):
self.do_something() # requires the do_something method always be called
def do_something(self):
raise NotImplementedError
class SubClass(SuperClass):
def __init__(self):
super(SuperClass, self).__init__() # this should do_something
def do_something(self):
print "hello"
I would like the SuperClass init to always call a not-yet-implemented do_something method. I'm using python 2.7. Perhaps ABC can do this, but it is there another way?
Thanks.
Your code is mostly correct, except for the use of super. You need to put the current class name in the super call, so it would be:
super(SubClass, self).__init__()
Since you put in the wrong class name, SuperClass.__init__ wasn't called, and as a result do_something wasn't called either.