Initially this was defined
class Mammal(object):
def __init__(self, name):
self.name = name
def get_name(self):
return self.name
def say(self):
return("What does the " + self.name + " says")
but now we want to create subclasses of Mammals, whose constructor will call the Mammal's constructor with the correct name.
class Dog(Mammal):
def __init__(self):
Dog.self
This is my code. It says type object 'Dog' has no attribute 'self' what's the problem?
when print(Dog().get_name()) I should get Dog.
If you are using Python 2.x, you should write
super(Dog, self).__init__('name')
or, for Python 3:
super().__init__('name')
instead of
Dog.self
See Understanding Python super() with __init__() methods for detail.
If you want Dog().get_name() to return 'Dog', you should call
super(Dog, self).__init__('Dog')
You should write like this:
class Dog(Mammal):
def __init__(self):
super().__init__('dog name')
Related
This question already has answers here:
__init__() missing 1 required positional argument: 'quantity'
(4 answers)
Closed last month.
class Parent:
def __init__(self, name):
self.name = name
def printName(self):
print(self.name)
class Child(Parent):
def __init__(self, name):
Parent.__init__(name)
bob = Child('Bob')
bob.printName()
It's working with super().__init__(name) but not with the class name, why?
It doesn't work since Parent.__init__ is defined to take two arguments: self and name, and you're passing just a single argument to it. Thus, if you want to call it like that, you need to use Parent.__init__(self, name). But there really is no point, and you should instead just use super().__init__(name), as you already know.
The init() method always requires the self parameter, which is a reference to the object itself. Without the self parameter, the init() method would not have access to the object's attributes and would not be able to initialize them properly. The fix can be found here.
class Parent:
def __init__(self, name):
self.name = name
def printName(self):
print(self.name)
class Child(Parent):
def __init__(self, name):
Parent.__init__(self, name)
bob = Child('Bob')
bob.printName()
That is because Parent.__init__() always requires self.
However, super().__init__() does not require self because it implicitly finds the self by MRO (Method Resolution Order). You can see the order using Class.__mro__, as follows:
class Parent:
def __init__(self, name):
self.name = name
def printName(self):
print(self.name)
class Child(Parent):
def __init__(self, name):
Parent.__init__(self, name)
bob = Child('Bob')
print(Child.__mro__)
# (<class '__main__.Child'>, <class '__main__.Parent'>, <class 'object'>)
Here, if you use super.__init__(name) instead of Parent.__init(self, name), it will find Parent by the order.
For more information: see https://docs.python.org/3/library/functions.html#super
[This is in Python 3.6.8] So my impression was that a subclass inheriting from a superclass would be able to access the superclass' attributes freely, even if the attribute was "private". For example:
class A():
def __init__(self, name):
self.__name = name
def __str__(self):
return f'my name is {self.__name}'
class B(A):
def __init__(self, name, number):
A.__init__(self, name)
self.__number = number
def __str__(self):
return f'my name is {self.__name}\nmy number is {self.__number}'
def main():
name = input('name: ')
number = input('number: ')
obj = B(name, number)
print(obj)
main()
Apparently, when I try to use self.__name in the __str__ function of the subclass B, it throws an AttributeError exception, stating: AttributeError: 'B' object has no attribute '_B__name'. However, the program works as intended when I use a accessor (getter) method for getting the name instead of self.__name. So was my initial impression wrong, or am I making a misunderstanding somewhere?
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 am currently learning how to program in Python I am stuck calling an attribute from a Parent class. In the example below, how can I call the attribute "name" on "daisy" to print the name. I always get an error "'Mammal' object has no attribute 'name'.
class Vertebrate:
spinal_cord = True
def __init__(self, name):
self.name = name
class Mammal(Vertebrate):
def __init__(self, name, animal_type):
self.animal_type = animal_type
self.temperature_regulation = True
daisy = Mammal('Daisy', 'dog')
print(daisy.name)
here I want to print the name which has been defined in the Vertebrate class, but I always get an error
"'Mammal' object has no attribute 'name'"
You need to call super in the __init__ of Mammal, like this:
class Mammal(Vertebrate):
def __init__(self, name, animal_type):
super().__init__(name)
self.animal_type = animal_type
self.temperature_regulation = True
When __init__ of Mammal is called, it doesn't automatically call the __init__ of it's parent class, that's what super does here.
When you assign an init function to the child class, it overrides the default init function of parent class being called. In such a case you need to explicitly call the parent class using the super function. You also need to assign the class Vertebrate to be a child of the class Object to be able to access all of the object's modules within it.
class Vertebrate(object):
def __init__(self, name):
self.name = name
spinal_cord = True
class Mammal(Vertebrate):
def __init__(self, name, animal_type):
super(Mammal, self).__init__(name)
self.animal_type = animal_type
self.temperature_regulation = True
animal = Mammal("Daisy", "dog")
print animal.name
I am trying to print a string variable returned by name() function, which in this case should print "Jim, but Python is printing
`<bound method Human.name of <__main__.Human object at 0x7f9a18e2aed0>>`
Below is the code.
class Human:
def __init__(self):
name = None
def setName(self, _name):
name = _name
def name(self):
return self.name
jim = Human()
jim.setName("Jim")
print(jim.name())
UPDATE:
After reading the answers, i updated the code as shown below, but, now i am getting a new error TypeError: 'str' object is not callable
class Human:
def __init__(self):
self.name = None
def setName(self, _name):
self.name = _name
def name(self):
return self.name
jim = Human()
jim.setName("Jim")
print(jim.name())
self.name is the method itself. You have no attributes storing the name. Nowhere do you actually set the name as an attribute. The following works:
class Human:
def __init__(self):
self.name = None
def setName(self, _name):
self.name = _name
# NOTE: There is no more name method here!
Now you have an actual attribute, and you don't need to call the method here:
jim = Human()
jim.setName("Jim")
print(jim.name) # directly using the attribute
You could even just set the attribute directly:
jim = Human()
jim.name = "Jim"
print(jim.name)
Alternatively, use self._name to store the name on the instance:
class Human:
_name = None
def setName(self, _name):
self._name = _name
def name(self):
return self._name
Here we used a class attribute Human._name as a default, and only set self._name on the instance in the Human.setName() method.
The problem is that name is the name of the internal variable in your object and also the name of the method.
The namespace for variables and methods is the same. Change the name of your method to something other than name. This will fix your getter. On first glance I thought that that would be all you have to do, but the recommendation in Martijn's answer also applies -- you need to assign to self.name and not just name in order to get your setter to work as well.
As an aside, this getter/setter pattern is not usually appropriate for Python. You should ask yourself why you want to use a getter/setter pattern over simply accessing the object's variable directly. See the section on getters and setters in this article for more detail.
You can use setter and getter properties instead of your custom defined methods.
class Human():
def __init__(self):
self._name = None
#property
def name(self):
return self._name
#name.setter
def name(self, name):
self._name = name
And then, use them:
jim = Human()
jim.name = "Jim"
print(jim.name)