Why not use self.varibale_name while calling instance attribute [duplicate] - python

This question already has answers here:
What is the purpose of the `self` parameter? Why is it needed?
(26 answers)
Closed 4 years ago.
when we create a class which is having instance attribute,why don't we call the instance attribute using self keyword.Please
class car:
def __init__(self, type, color):
self.type = type
self.color = color
c1 = car('SUV','Red')
print(c1.type)
Why not print(c1.self.type), because self.type is the actual attribute.
Got the following error:
AttributeError: 'car' object has no attribute 'self'

When you're describing methods (__init__ in your case), self is refers to instance, that will be passed in future — you need this, because you don't know what instances will be created from your class after.
When you're building instance with c1 = car(...):
at first, python makes "empty" object and assigns it to c1
then this empty object being passed to initializer, roughly as car.__init__(c1, 'SUV', 'Red')
And your __init__ actually mutates c1, just by referencing to that object as self.
Here's example that may help you better understand, step by step.
Python objects is not restricted by any schema of fields (by default). This means that you can add or remove attributes in runtime – after instance been created:
class Car:
pass #does nothing
car = Car()
car.color = 'red'
car.type = 'SUV'
You have class that does not describe anything, except the name, you can add type/color/whatever you want after object creation.
The downside of this – there's a huge room to make mistake, plus you need to write a lot of code as your data model grows.
The next logical step to take - make a "mutation" function, that takes object + required attribute values, and bundle all mutation logic in one place:
class Car:
pass
def prepare_car(car_instance, color, type):
car_instance.color = color
car_instance.type = type
car = SimpleCar()
prepare_car(color='red', type='SUV')
Now all mutation logic is in one place, any user can call the same call, no need to re-write all mutation code every time. Logically, code that mutates car, is highly related to SimpleCar class (well, because it changes car color and type). It would be good to have it bound to class somehow. Let's move it to class namespace:
class Car:
def prepare_car(car_instance, color, type):
car_instance.color = color
car_instance.type = type
we've just moved our function in scope of object. What does that mean for us? To access that function, we need to provide "namespace" first, i.e. Car.prepare_car – reads as "take a class Car_, look for prepare_car method". Now we can call it with
car = Car()
Car.prepare_car(car, color='red', type='SUV')
Here come the magic of python OOP. Once you have instance of a class, you can call methods on instance itself, not from class scope. And what happens when you do so – python will automatically pass instance itself as first argument to function:
car = Car()
Car.prepare_car(car, color='red', type='SUV') # calling class.function
is the same as
car = Car()
car.prepare_car(color='red', type='SUV') # calling instance.method
This is the reason why first argument for methods usually called self this is only convention, but it reads good, consider re-factored code
class Car:
def prepare(self, color, type):
self.color = color
self.type = type
car = Car()
car.prepare(color='red', type='SUV')
now method is called prepare, not prepare_car, because we know what we'll mutate – this is in scope of Car class, so we expect this function to interact with Cars. First argument now called self, because we'll mostly call it on instances (like my_car.prepare(...)), so instance changes itself.
And finally, the __init__. This method (if provided) will be automatically called on instance after it's been created, and signature for instantiating class changes accordingly. Lets make prepare method and initiation part:
class Car:
def __init__(self, color, type):
self.color = color
self.type = type
car = Car(color='red', type='SUV')

Related

How to access a parent instance variable using super()

I was playing around a bit with polymorphism and super() in python classes with inheritance and found that I didn't understand the following behavior.
In this dummy example, I found that I can access the instance variables and class variables for the child class, and class variable for the parent class, directly from the object of the child class, BUT I was unsuccessful in accessing the instance variable for the parent class.
I understand that I would have to create an object of the parent class using super() but am unable to access the instance variables from parent class. I don't want to explicitly return anything in the parent.__init__().
The only way I found to do this is to explicitly create an object of the parent class and then fetch the required variable, but that hinders proper abstraction of the code.
Is there a way I can access parent_object._color after its constructor is run, using super(), without explicit instantiation of the parent class object?
#parent class
class hat:
_color = 'red' #Parent class variable
def __init__(self):
self._color = 'yellow' #Parent object variable
#child class
class cap(hat):
_color = 'green' #Child class variable
def __init__(self, color): #Child instance variable (passed)
self._color = color
#property
def parent_color_super(self):
return super()._color #super() only gives access to class variables
#property
def parent_color_explicit(self):
return hat()._color #explicit object constructor allows access to instance variable
c = cap('blue')
print(c._color) #Attribute lookup: Instance variable
print(c.__class__._color) #Attribute lookup: class variable
print(c.__class__.__bases__[0]._color) #Attribute lookup: parent class variable
print(c.parent_color_super) #<---
print(c.parent_color_explicit) #<---
blue
green
red
red #<--- how to get this as yellow!
yellow #<---
EDIT 2:
Based on the valuable answers from #Silvio Mayolo, #user2357112, and #Mad Physicist, I think I understand where the issue was.
As I understand, the child class's instance c will hold the instance variable _color which will get overwritten by the super().__init__() as the job of that function is to update the self._color of whichever object its called from.
This means, as clarified by the answers, there is no separate "parent instance variables" that can be accessed by super(); only class attributes such as the class variable _color (red) and __init__() (which sets the instance variable _color to (yellow).
A modified example to show this behavior is as follows -
class hat:
_color = 'red' #Parent class variable
def __init__(self): #Sets instance variable to yellow
self._color = 'yellow'
class cap(hat):
_color = 'green' #Child class variable
def __init__(self, color): #Child instance variable (passed)
self._color = color
def parent_color_super(self): #Call __init__ from parent, overwrites _color
super().__init__()
c = cap('blue')
print(c._color) #Attribute lookup: Instance variable
print(c.__class__._color) #Attribute lookup: class variable
print(c.__class__.__bases__[0]._color) #Attribute lookup: parent class variable
c.parent_color_super() #Call init from super class
print(c._color) #Attribute lookup: Updated Instance variable
blue
green
red
yellow
There is no separate set of parent class instance variables. The instance variable you are trying to access does not exist. The only instance variable your c has is a single _color instance variable, set to 'blue'.
Your parent_color_explicit does not access what you're trying to access. It creates an entirely separate, completely unrelated instance of hat, and accesses that instance's instance variables.
Heck, you never even called super().__init__ in cap.__init__, so the self._color = 'yellow' assignment never happens at all for c. (It wouldn't solve your problem if you did call super().__init__, because self._color can't be both 'yellow' and 'blue'. Only one of those values would be saved, depending on which assignment happens second.)
Instance variables and methods are fundamentally different beasts. A method, generally speaking, is defined on a class. It happens to be called on an instance, but it doesn't, in any reasonable sense, exist on that instance. More concretely
class Hat:
_color = 'red'
def __init__(self, color):
self._color = color
def example(self):
print("I'm a Hat")
class Cap(Hat):
_color = 'green'
def __init__(self, color):
self._color = color
def example(self):
print("I'm a Cap")
my_hat = Hat('yellow')
my_cap = Cap('orange')
Let's be perfectly clear about what's happening here. Hat is a class which has three slots defined on it: _color, __init__, and example. Cap is also a class (a subclass of Hat) which has three slots defined on it: _color, __init__, and example. In each case, _color is a string and the other two are functions. Ordinary Python functions at this point, not instance methods. The instance method magic comes later using __get__.
Now, my_hat is a hat. To construct it, we allocated some memory for a new object called my_hat and then called Hat.__init__(my_hat, 'yellow'). This set the _color field on my_hat (which is unrelated to the _color field on Hat at this point). If we were to, at this point, call my_hat.example(), that would end up calling Hat.example(my_hat), through the __get__ magic method on function. Note carefully: At no point is example actually defined on my_hat. It's defined on the class Hat and then the rules of Python allow us to access it as my_hat.example().
Now, with my_cap, we allocate some memory and call Cap.__init__(my_cap, 'orange'). This initializes the instance variable _color to 'orange'. In your current code, we never call the superclass constructor, but even if we did do super().__init__('purple'), the result would get overwritten. The object my_cap can only have _color defined on it once. There's no virtual inheritance for that: it's literally defined on the object, in the exact same way a key is given a value in a dictionary.
The reason super() works for methods is that the parent method still exists on the parent class. Methods aren't called on objects, they're called on classes and happen to take an instance of that class as the first argument. So when we want to access a parent class method, we can simply do Hat.example(my_cap). The super() syntax just automates this process. By contrast, in the case of instance variables that are literally defined on the object, not on a class, the old value is gone as soon as you overwrite it. It never existed at that point. The fact that there are class-level variables with the same name is irrelevant, those serve no purpose to an instance which has already defined a field with the same name.
If you want virtual inheritance, you need names to be defined on the class. So you need functions, or if you want the property syntax, you need #property. At some point, you're going to have to access a (real, concrete, non-virtual) backing field, but you can hide that behind #property if you like.
class Hat:
def __init__(self):
self._Hat_color = 'yellow'
class Cap(Hat):
def __init__(self, color):
super().__init__()
self._Cap_color = color
#property
def hat_color(self):
return self._Hat_color
my_hat = Hat('yellow')
my_cap = Cap('orange')
If you want to automate the process of mangling instance variable names from child classes even further, you can use dunder variables. self.__color will get renamed to self._Hat__color internally if used inside of Hat. It's just a trick of naming, not any deeper magic, but it can help with avoiding conflicts.
You are missing the point of how method inheritance works. Since your child class defines an __init__ method that does not call super().__init__, the line self._color = 'yellow' will never be called.
There are a couple of things you can do. One option is to call super().__init__() somehow:
def __init__(self, color):
self._color = color
super().__init__()
Now of course you lose the input variable color since it gets overwritten by 'yellow' no matter what.
Another alternative is to call super().__init__() on the instance. __init__ is just a regular method as far as you are concerned, so you don't need to call an allocator to call it:
#property
def parent_color_explicit(self):
color = self._color
super().__init__()
color, self._color = self._color, color
return color
The point is that an instance contains one __dict__. That dictionary can contain one single instance of the _color key. You can access the __dict__ of parent classes via super(), but for the most part that will give you access to a bunch of alternative method implementations. Those implementations still operate on the one and only instance dictionary.
If you want to have multiple definitions of a thing, name it something else in instances of the child class.

Why is "self" in "__init__" method in python neccessary? [duplicate]

This question already has answers here:
What is the purpose of the `self` parameter? Why is it needed?
(26 answers)
Why do we use __init__ in Python classes?
(9 answers)
Closed 6 months ago.
I'm learning the Python programming language and I've came across something I don't fully understand.
In a method like:
def method(self, blah):
def __init__(?):
....
....
What does self do? What is it meant to be? Is it mandatory?
What does the __init__ method do? Why is it necessary? (etc.)
I think they might be OOP constructs, but I don't know very much.
In this code:
class A(object):
def __init__(self):
self.x = 'Hello'
def method_a(self, foo):
print self.x + ' ' + foo
... the self variable represents the instance of the object itself. Most object-oriented languages pass this as a hidden parameter to the methods defined on an object; Python does not. You have to declare it explicitly. When you create an instance of the A class and call its methods, it will be passed automatically, as in ...
a = A() # We do not pass any argument to the __init__ method
a.method_a('Sailor!') # We only pass a single argument
The __init__ method is roughly what represents a constructor in Python. When you call A() Python creates an object for you, and passes it as the first parameter to the __init__ method. Any additional parameters (e.g., A(24, 'Hello')) will also get passed as arguments--in this case causing an exception to be raised, since the constructor isn't expecting them.
Yep, you are right, these are oop constructs.
__init__ is the constructor for a class. The self parameter refers to the instance of the object (like this in C++).
class Point:
def __init__(self, x, y):
self._x = x
self._y = y
The __init__ method gets called after memory for the object is allocated:
x = Point(1,2)
It is important to use the self parameter inside an object's method if you want to persist the value with the object. If, for instance, you implement the __init__ method like this:
class Point:
def __init__(self, x, y):
_x = x
_y = y
Your x and y parameters would be stored in variables on the stack and would be discarded when the init method goes out of scope. Setting those variables as self._x and self._y sets those variables as members of the Point object (accessible for the lifetime of the object).
N.B. Some clarification of the use of the word "constructor" in this answer. Technically the responsibilities of a "constructor" are split over two methods in Python. Those methods are __new__ (responsible for allocating memory) and __init__ (as discussed here, responsible for initialising the newly created instance).
A brief illustrative example
In the hope it might help a little, here's a simple example I used to understand the difference between a variable declared inside a class, and a variable declared inside an __init__ function:
class MyClass(object):
i = 123
def __init__(self):
self.i = 345
a = MyClass()
print(a.i)
print(MyClass.i)
Output:
345
123
In short:
self as it suggests, refers to itself- the object which has called the method. That is, if you have N objects calling the method, then self.a will refer to a separate instance of the variable for each of the N objects. Imagine N copies of the variable a for each object
__init__ is what is called as a constructor in other OOP languages such as C++/Java. The basic idea is that it is a special method which is automatically called when an object of that Class is created
Class objects support two kinds of operations: attribute references and instantiation
Attribute references use the standard syntax used for all attribute references in Python: obj.name. Valid attribute names are all the names that were in the class’s namespace when the class object was created. So, if the class definition looked like this:
class MyClass:
"""A simple example class"""
i = 12345
def f(self):
return 'hello world'
then MyClass.i and MyClass.f are valid attribute references, returning an integer and a function object, respectively. Class attributes can also be assigned to, so you can change the value of MyClass.i by assignment. __doc__ is also a valid attribute, returning the docstring belonging to the class: "A simple example class".
Class instantiation uses function notation. Just pretend that the class object is a parameterless function that returns a new instance of the class. For example:
x = MyClass()
The instantiation operation (“calling” a class object) creates an empty object. Many classes like to create objects with instances customized to a specific initial state. Therefore a class may define a special method named __init__(), like this:
def __init__(self):
self.data = []
When a class defines an __init__() method, class instantiation automatically invokes __init__() for the newly-created class instance. So in this example, a new, initialized instance can be obtained by:
x = MyClass()
Of course, the __init__() method may have arguments for greater flexibility. In that case, arguments given to the class instantiation operator are passed on to __init__(). For example,
class Complex:
def __init__(self, realpart, imagpart):
self.r = realpart
self.i = imagpart
x = Complex(3.0, -4.5)
x.r, x.i
Taken from official documentation which helped me the most in the end.
Here is my example
class Bill():
def __init__(self,apples,figs,dates):
self.apples = apples
self.figs = figs
self.dates = dates
self.bill = apples + figs + dates
print ("Buy",self.apples,"apples", self.figs,"figs
and",self.dates,"dates.
Total fruitty bill is",self.bill," pieces of fruit :)")
When you create instance of class Bill:
purchase = Bill(5,6,7)
You get:
> Buy 5 apples 6 figs and 7 dates. Total fruitty bill is 18 pieces of
> fruit :)
__init__ does act like a constructor. You'll need to pass "self" to any class functions as the first argument if you want them to behave as non-static methods. "self" are instance variables for your class.
Try out this code. Hope it helps many C programmers like me to Learn Py.
#! /usr/bin/python2
class Person:
'''Doc - Inside Class '''
def __init__(self, name):
'''Doc - __init__ Constructor'''
self.n_name = name
def show(self, n1, n2):
'''Doc - Inside Show'''
print self.n_name
print 'Sum = ', (n1 + n2)
def __del__(self):
print 'Destructor Deleting object - ', self.n_name
p=Person('Jay')
p.show(2, 3)
print p.__doc__
print p.__init__.__doc__
print p.show.__doc__
Output:
Jay
Sum = 5
Doc - Inside Class
Doc - __init__ Constructor
Doc - Inside Show
Destructor Deleting object - Jay
Had trouble undestanding this myself. Even after reading the answers here.
To properly understand the __init__ method you need to understand self.
The self Parameter
The arguments accepted by the __init__ method are :
def __init__(self, arg1, arg2):
But we only actually pass it two arguments :
instance = OurClass('arg1', 'arg2')
Where has the extra argument come from ?
When we access attributes of an object we do it by name (or by reference). Here instance is a reference to our new object. We access the printargs method of the instance object using instance.printargs.
In order to access object attributes from within the __init__ method we need a reference to the object.
Whenever a method is called, a reference to the main object is passed as the first argument. By convention you always call this first argument to your methods self.
This means in the __init__ method we can do :
self.arg1 = arg1
self.arg2 = arg2
Here we are setting attributes on the object. You can verify this by doing the following :
instance = OurClass('arg1', 'arg2')
print instance.arg1
arg1
values like this are known as object attributes. Here the __init__ method sets the arg1 and arg2 attributes of the instance.
source: http://www.voidspace.org.uk/python/articles/OOP.shtml#the-init-method
note that self could actually be any valid python identifier. For example, we could just as easily write, from Chris B's example:
class A(object):
def __init__(foo):
foo.x = 'Hello'
def method_a(bar, foo):
print bar.x + ' ' + foo
and it would work exactly the same. It is however recommended to use self because other pythoners will recognize it more easily.
What does self do? What is it meant to be? Is it mandatory?
The first argument of every class method, including init, is always a reference to the current instance of the class. By convention, this argument is always named self. In the init method, self refers to the newly created object; in other class methods, it refers to the instance whose method was called.
Python doesn't force you on using "self". You can give it any name you want. But remember the first argument in a method definition is a reference to the object. Python adds the self argument to the list for you; you do not need to include it when you call the methods.
if you didn't provide self in init method then you will get an error
TypeError: __init___() takes no arguments (1 given)
What does the init method do? Why is it necessary? (etc.)
init is short for initialization. It is a constructor which gets called when you make an instance of the class and it is not necessary. But usually it our practice to write init method for setting default state of the object. If you are not willing to set any state of the object initially then you don't need to write this method.
__init__ is basically a function which will "initialize"/"activate" the properties of the class for a specific object, once created and matched to the corresponding class..
self represents that object which will inherit those properties.
Basically, you need to use the 'self' keyword when using a variable in multiple functions within the same class. As for init, it's used to setup default values incase no other functions from within that class are called.
The 'self' is a reference to the class instance
class foo:
def bar(self):
print "hi"
Now we can create an instance of foo and call the method on it, the self parameter is added by Python in this case:
f = foo()
f.bar()
But it can be passed in as well if the method call isn't in the context of an instance of the class, the code below does the same thing
f = foo()
foo.bar(f)
Interestingly the variable name 'self' is just a convention. The below definition will work exactly the same.. Having said that it is very strong convention which should be followed always, but it does say something about flexible nature of the language
class foo:
def bar(s):
print "hi"
Just a demo for the question.
class MyClass:
def __init__(self):
print('__init__ is the constructor for a class')
def __del__(self):
print('__del__ is the destructor for a class')
def __enter__(self):
print('__enter__ is for context manager')
return self
def __exit__(self, exc_type, exc_value, traceback):
print('__exit__ is for context manager')
def greeting(self):
print('hello python')
if __name__ == '__main__':
with MyClass() as mycls:
mycls.greeting()
$ python3 class.objects_instantiation.py
__init__ is the constructor for a class
__enter__ is for context manager
hello python
__exit__ is for context manager
__del__ is the destructor for a class
In this code:
class Cat:
def __init__(self, name):
self.name = name
def info(self):
print 'I am a cat and I am called', self.name
Here __init__ acts as a constructor for the class and when an object is instantiated, this function is called. self represents the instantiating object.
c = Cat('Kitty')
c.info()
The result of the above statements will be as follows:
I am a cat and I am called Kitty
# Source: Class and Instance Variables
# https://docs.python.org/2/tutorial/classes.html#class-and-instance-variables
class MyClass(object):
# class variable
my_CLS_var = 10
# sets "init'ial" state to objects/instances, use self argument
def __init__(self):
# self usage => instance variable (per object)
self.my_OBJ_var = 15
# also possible, class name is used => init class variable
MyClass.my_CLS_var = 20
def run_example_func():
# PRINTS 10 (class variable)
print MyClass.my_CLS_var
# executes __init__ for obj1 instance
# NOTE: __init__ changes class variable above
obj1 = MyClass()
# PRINTS 15 (instance variable)
print obj1.my_OBJ_var
# PRINTS 20 (class variable, changed value)
print MyClass.my_CLS_var
run_example_func()
Here, the guy has written pretty well and simple: https://www.jeffknupp.com/blog/2014/06/18/improve-your-python-python-classes-and-object-oriented-programming/
Read above link as a reference to this:
self? So what's with that self parameter to all of the Customer
methods? What is it? Why, it's the instance, of course! Put another
way, a method like withdraw defines the instructions for withdrawing
money from some abstract customer's account. Calling
jeff.withdraw(100.0) puts those instructions to use on the jeff
instance.
So when we say def withdraw(self, amount):, we're saying, "here's how
you withdraw money from a Customer object (which we'll call self) and
a dollar figure (which we'll call amount). self is the instance of the
Customer that withdraw is being called on. That's not me making
analogies, either. jeff.withdraw(100.0) is just shorthand for
Customer.withdraw(jeff, 100.0), which is perfectly valid (if not often
seen) code.
init self may make sense for other methods, but what about init? When we call init, we're in the process of creating an object, so how can there already be a self? Python allows us to extend
the self pattern to when objects are constructed as well, even though
it doesn't exactly fit. Just imagine that jeff = Customer('Jeff
Knupp', 1000.0) is the same as calling jeff = Customer(jeff, 'Jeff
Knupp', 1000.0); the jeff that's passed in is also made the result.
This is why when we call init, we initialize objects by saying
things like self.name = name. Remember, since self is the instance,
this is equivalent to saying jeff.name = name, which is the same as
jeff.name = 'Jeff Knupp. Similarly, self.balance = balance is the same
as jeff.balance = 1000.0. After these two lines, we consider the
Customer object "initialized" and ready for use.
Be careful what you __init__
After init has finished, the caller can rightly assume that the
object is ready to use. That is, after jeff = Customer('Jeff Knupp',
1000.0), we can start making deposit and withdraw calls on jeff; jeff is a fully-initialized object.
Python __init__ and self what do they do?
What does self do? What is it meant to be? Is it mandatory?
What does the __init__ method do? Why is it necessary? (etc.)
The example given is not correct, so let me create a correct example based on it:
class SomeObject(object):
def __init__(self, blah):
self.blah = blah
def method(self):
return self.blah
When we create an instance of the object, the __init__ is called to customize the object after it has been created. That is, when we call SomeObject with 'blah' below (which could be anything), it gets passed to the __init__ function as the argument, blah:
an_object = SomeObject('blah')
The self argument is the instance of SomeObject that will be assigned to an_object.
Later, we might want to call a method on this object:
an_object.method()
Doing the dotted lookup, that is, an_object.method, binds the instance to an instance of the function, and the method (as called above) is now a "bound" method - which means we do not need to explicitly pass the instance to the method call.
The method call gets the instance because it was bound on the dotted lookup, and when called, then executes whatever code it was programmed to perform.
The implicitly passed self argument is called self by convention. We could use any other legal Python name, but you will likely get tarred and feathered by other Python programmers if you change it to something else.
__init__ is a special method, documented in the Python datamodel documentation. It is called immediately after the instance is created (usually via __new__ - although __new__ is not required unless you are subclassing an immutable datatype).

Python inheritance: when and why __init__

I'm a Python newbie, trying to understand the philosophy/logic behind the inheritance methods. Questions ultimately regards why and when one has to use the __init__ method in a subclass. Example:
It seems a subclass inheriting from a superclass need not have its own constructor (__init__) method. Below, a dog inherits the attributes (name, age) and methods (makenoise) of a mammal. You can even add a method (do_a_trick) Everything works as it ``should", it seems.
However, if I wanted to add a new attribute in the subclass as I attempt to do in the Cats class, I get an error saying "self" is not defined. Yet I used "self" in the definition of the dog class. What's the nature of the difference?
It seems to define Cats as I wish I need to use __init__(self,name) and super()__init__(name). Why the difference?
class Mammals(object):
def __init__(self,name):
self.name = name
print("I am a new-born "+ self.name)
self.age = 0
def makenoise(self):
print(self.name + " says Hello")
class Dogs(Mammals):
def do_a_trick(self):
print(self.name + " can roll over")
class Cats(Mammals):
self.furry = "True" #results in error `self' is not defined
mymammal = Mammals("zebra") #output "I am a new-born zebra"
mymammal.makenoise() #output "zebra says hello"
print(mymmmal.age) #output 0
mydog = Dogs("family pet") #output "I am a new-born family pet"
mydog.makenoise() #output "family pet says hello"
print(mydog.age) # output 0
mydog.do_a_trick() #output "family pet can roll over"
Explicit is better than implicit.
However, you can do below:
class Dogs(Mammals):
def __init__(self):
#add new attribute
self.someattribute = 'value'
Mammals.__init__(self)
or
class Dogs(Mammals):
def __init__(self):
#add new attribute
self.someattribute = 'value'
super(Mammals, self).__init__()
if I wanted to add a new attribute in the subclass as I attempt to do
in the Cats class, I get an error saying "self" is not defined. Yet I
used "self" in the definition of the dog class.
In your superclass, Mammal, you have an __init__ function, which takes an argument that you've chosen* to call self. This argument is in scope when you're in the body of the __init__ function - it's a local variable like any local variable, and it's not possible to refer to it after its containing function terminates.
The function defined on the Dog class, do_a_trick, also takes an argument called self, and it is also local to that function.
What makes these variables special is not their name (you could call them anything you wanted) but the fact that, as the first arguments to instance methods in python, they get a reference to the object on which they're called as their value. (Read that last sentence again a few times, it's the key to understanding this, and you probably won't get it the first time.)
Now, in Cat, you have a line of code which is not in a function at all. Nothing is in scope at this point, including self, which is why this fails. If you were to define a function in Cat that took an argument called self, it would be possible to refer to that argument. If that argument happened to be the first argument to an instance method on Cat, then it would have the value of the instance of Cat on which it had been called. Otherwise, it would have whatever got passed to it.
*you have chosen wisely!
Declarations at the top level of a Python class become class attributes. If you come from a C++ or Java background, this is similar to declaring a static member variable. You cannot assign instance attributes at that level.
The variable self usually refers to a specific instance of a class, the one from which the method has been called. When a method call is made using the syntax inst.method(), the first argument to the function is the object inst on which the method was called. In your case, and usually by convention, that argument is named self within the function body of methods. You can think of self as only being a valid identifier within method bodies then. Your assignment self.furry = True does not take place in a method, so self isn't defined there.
You have basically two options for achieving what you want. The first is to properly define furry as an attribute of the cat class:
class Cat(Mammals):
furry = True
# Rest of Cat implementation ...
or you can set the value of an instance variable furry in the cat constructor:
class Cat(Mammals):
def __init__(self):
super(Mammals, self).__init__(self)
self.furry = True
# Rest of Cat implementation ...
If you're getting into Python I highly recommend to read these two parts of the Python documentation:
Python classes
Python data model special methods (more advanced)
As pointed out in the other answers, the self that you see in the other
functions is actually a parameter. By Python convention, the first parameter in
an instance method is always self.
The class Cats inherits the __init__ function from its base class,
Mammals. You can override __init__, and you can call or not call the base
class implementation.
In case the Cats __init__ wants to call the base implementation, but doesn't want to care about the parameters, you can use Python variable arguments. This is shown in the following code.
Class declaration:
class Cats(Mammals):
def __init__(self, *args):
super().__init__(*args)
self.furry = "True"
See, for example, this Stack Overflow question for something about the star
notation for variable numbers of arguments:
Can a variable number of arguments be passed to a function?
Additional test code:
cat = Cats("cat")
print(vars(cat))
Output:
I am a new-born cat
{'name': 'cat', 'age': 0, 'furry': 'True'}
You can do something like in Chankey's answer by initiating all the variables in the constructor method ie __init__
However you can also do something like this
class Cats(Mammals):
furry = "True"
And then
cat = Cats("Tom")
cat.furry # Returns "True"
The reason you can't use self outside the functions is because self is used explicitly only for instances of the class. If you used it outside, it would lead to ambiguity. If my answer isn't clear please let me know in comments.
The __init__ method runs once on the creation of an instance of a class. So if you want to set an attribute on an instance when it's created, that's where you do it. self is a special keyword that is passed as the first argument to every method, and it refers to the instance itself. __init__ is no different from other methods in this regard.
"What's the nature of the difference": you define the method Dog.do_a_trick, and you receive self as an argument to the method as usual. But in Cat you've unintentionally (perhaps subconsciously!) attempted to work on the class scope -- this is how you'd set a class attribute whose value is identical for all cats:
class Cat(object):
sound = "meow"
It's different so you can have both options available. Sometimes (not all the time, but once in a while) a class attribute is a useful thing to have. All cats have the same sound. But much of the time you'll work with instance attributes -- different cats have different names; when you need that, use __init__.
Suppose you have a class named Person which has a method named get_name defined as :
class Person():
def __init__(self, first_name, last_name):
self.first_name = first_name
self.last_name = last_name
def get_name(self):
return self.first_name + ' ' + self.last_name
And, you create an instance of Person as p1. Now when you call the function get_name() with this instance, it will converts internally
Person.get_name(p1)
So, self is the instance itself.
Without self you can write above code as :
class Person():
first_name = None
last_name = None
def get_name(personobject):
return personobject.first_name + ' ' + personobject.last_name
What I am trying to say is the name self is a convention only.
And for inheritance, if you would like to have extra attributes in your subclass, you need to initiate your super class first and add your parameter as you wanted.
For example, if you want to create a subclass from Person named Boy with new attribute height, the you can define it as:
class Boy(Person):
def __init__(self, first_name, last_name, height):
super(Person, self).__init__(first_name, last_name)
self.height = height

How do I call on a parent class in a subclass?

I need to create an UNBOUND method call to Plant to setup name and leaves and I don't know how. Any help is appreciated.
My code:
class Plant(object):
def __init__(self, name : str, leaves : int):
self.plant_name = name
self.leaves = leaves
def __str__(self):
return "{} {}".format(self.plant_name, self.leaves)
def __eq__(self, plant1):
if self.leaves == plant1.leaves:
return self.leaves
def __It__(self, plant1):
if self.leaves < plant1.leaves:
print ("{} has more leaves than {}".format(plant1.plant_name, self.plant_name))
return self.leaves < plant1.leaves
elif self.leaves > plant1.leaves:
print ("{} has more leaves than {}".format(self.plant_name, plant1.plant_name))
return self.leaves < plant1.leaves
class Flower(Plant):
def __init__(self, color : str, petals : int):
self.color = color
self.petals = petals
def pick_petal(self.petals)
self.petals += 1
Exact wording of the assignment:
Create a new class called Flower. Flower is subclassed from the Plant class; so besides name, and leaves, it adds 2 new attributes; color, petals. Color is a string that contains the color of the flower, and petal is an int that has the number of petals on the flower. You should be able to create an init method to setup the instance. With the init you should make an UNBOUND method call to plant to setup the name and leaves. In addition, create a method called pick_petal that decrements the number of petals on the flower.
An "unbound method call" means you're calling a method on the class rather than on an instance of the class. That means something like Plant.some_method.
The only sort of unbound call that makes sense in this context is to call the __init__ method of the base class. That seems to fulfill the requirement to "setup the names and leaves", and in the past was the common way to do inheritance.
It looks like this:
class Flower(Plant):
def __init__(self, name, leaves, color, petals):
Plant.__init__(self, ...)
...
You will need to pass in the appropriate arguments to __init__. The first is self, the rest are defined by Plant.__init__ in the base class. You'll also need to fix the syntax for the list of arguments, as `color : str' is not valid python.
Note: generally speaking, a better solution is to call super rather than doing an unbound method call on the parent class __init__. I'm not sure what you can do with that advice, though. Maybe the instructor is having you do inheritance the old way first before learning the new way?
For this assignment you should probably use Plant.__init__(...) since that's what the assignment is explicitly asking you to do. You might follow up with the instructor to ask about super.
The answer from Bryan is perfect. Just for the sake of completion:
# Looks like the assignment asks for this
class Flower(Plant):
def __init__(self, name, leaves, color, petals):
# call __init__ from parent so you don't repeat code already there
Plant.__init__(self, name, leaves)
self.color = color
self.petals = petals
This is the "classic", "non-cooperative" inheritance style and came out of fashion a long time ago (almost 15 years as of 2016), because it breaks with multiple inheritance. For reference see the post "Unifying types and classes in Python 2.2" by the BDFL. At first I thought it could be a very old assignment, but I see the assignment uses the "new-style" inheritance (inheriting from object was the signature of the new-style in Python 2 because the default is the old-style, in Python 3 there is only the new-style). In order to make it work for multiple inheritance, instead of calling the parent class explicitly (the Plant.__init__ statement), we use the super function like this in Python 2:
super(Flower, self).__init__(name, leaves)
Or just this after Python 3 (after PEP 0367 to be precise):
super().__init__(name, leaves)
Even if in Python 3 the new-style of inheritance is the default, you are still encouraged to explicitly inherit from object.

What do __init__ and self do in Python? [duplicate]

This question already has answers here:
What is the purpose of the `self` parameter? Why is it needed?
(26 answers)
Why do we use __init__ in Python classes?
(9 answers)
Closed 6 months ago.
I'm learning the Python programming language and I've came across something I don't fully understand.
In a method like:
def method(self, blah):
def __init__(?):
....
....
What does self do? What is it meant to be? Is it mandatory?
What does the __init__ method do? Why is it necessary? (etc.)
I think they might be OOP constructs, but I don't know very much.
In this code:
class A(object):
def __init__(self):
self.x = 'Hello'
def method_a(self, foo):
print self.x + ' ' + foo
... the self variable represents the instance of the object itself. Most object-oriented languages pass this as a hidden parameter to the methods defined on an object; Python does not. You have to declare it explicitly. When you create an instance of the A class and call its methods, it will be passed automatically, as in ...
a = A() # We do not pass any argument to the __init__ method
a.method_a('Sailor!') # We only pass a single argument
The __init__ method is roughly what represents a constructor in Python. When you call A() Python creates an object for you, and passes it as the first parameter to the __init__ method. Any additional parameters (e.g., A(24, 'Hello')) will also get passed as arguments--in this case causing an exception to be raised, since the constructor isn't expecting them.
Yep, you are right, these are oop constructs.
__init__ is the constructor for a class. The self parameter refers to the instance of the object (like this in C++).
class Point:
def __init__(self, x, y):
self._x = x
self._y = y
The __init__ method gets called after memory for the object is allocated:
x = Point(1,2)
It is important to use the self parameter inside an object's method if you want to persist the value with the object. If, for instance, you implement the __init__ method like this:
class Point:
def __init__(self, x, y):
_x = x
_y = y
Your x and y parameters would be stored in variables on the stack and would be discarded when the init method goes out of scope. Setting those variables as self._x and self._y sets those variables as members of the Point object (accessible for the lifetime of the object).
N.B. Some clarification of the use of the word "constructor" in this answer. Technically the responsibilities of a "constructor" are split over two methods in Python. Those methods are __new__ (responsible for allocating memory) and __init__ (as discussed here, responsible for initialising the newly created instance).
A brief illustrative example
In the hope it might help a little, here's a simple example I used to understand the difference between a variable declared inside a class, and a variable declared inside an __init__ function:
class MyClass(object):
i = 123
def __init__(self):
self.i = 345
a = MyClass()
print(a.i)
print(MyClass.i)
Output:
345
123
In short:
self as it suggests, refers to itself- the object which has called the method. That is, if you have N objects calling the method, then self.a will refer to a separate instance of the variable for each of the N objects. Imagine N copies of the variable a for each object
__init__ is what is called as a constructor in other OOP languages such as C++/Java. The basic idea is that it is a special method which is automatically called when an object of that Class is created
Class objects support two kinds of operations: attribute references and instantiation
Attribute references use the standard syntax used for all attribute references in Python: obj.name. Valid attribute names are all the names that were in the class’s namespace when the class object was created. So, if the class definition looked like this:
class MyClass:
"""A simple example class"""
i = 12345
def f(self):
return 'hello world'
then MyClass.i and MyClass.f are valid attribute references, returning an integer and a function object, respectively. Class attributes can also be assigned to, so you can change the value of MyClass.i by assignment. __doc__ is also a valid attribute, returning the docstring belonging to the class: "A simple example class".
Class instantiation uses function notation. Just pretend that the class object is a parameterless function that returns a new instance of the class. For example:
x = MyClass()
The instantiation operation (“calling” a class object) creates an empty object. Many classes like to create objects with instances customized to a specific initial state. Therefore a class may define a special method named __init__(), like this:
def __init__(self):
self.data = []
When a class defines an __init__() method, class instantiation automatically invokes __init__() for the newly-created class instance. So in this example, a new, initialized instance can be obtained by:
x = MyClass()
Of course, the __init__() method may have arguments for greater flexibility. In that case, arguments given to the class instantiation operator are passed on to __init__(). For example,
class Complex:
def __init__(self, realpart, imagpart):
self.r = realpart
self.i = imagpart
x = Complex(3.0, -4.5)
x.r, x.i
Taken from official documentation which helped me the most in the end.
Here is my example
class Bill():
def __init__(self,apples,figs,dates):
self.apples = apples
self.figs = figs
self.dates = dates
self.bill = apples + figs + dates
print ("Buy",self.apples,"apples", self.figs,"figs
and",self.dates,"dates.
Total fruitty bill is",self.bill," pieces of fruit :)")
When you create instance of class Bill:
purchase = Bill(5,6,7)
You get:
> Buy 5 apples 6 figs and 7 dates. Total fruitty bill is 18 pieces of
> fruit :)
__init__ does act like a constructor. You'll need to pass "self" to any class functions as the first argument if you want them to behave as non-static methods. "self" are instance variables for your class.
Try out this code. Hope it helps many C programmers like me to Learn Py.
#! /usr/bin/python2
class Person:
'''Doc - Inside Class '''
def __init__(self, name):
'''Doc - __init__ Constructor'''
self.n_name = name
def show(self, n1, n2):
'''Doc - Inside Show'''
print self.n_name
print 'Sum = ', (n1 + n2)
def __del__(self):
print 'Destructor Deleting object - ', self.n_name
p=Person('Jay')
p.show(2, 3)
print p.__doc__
print p.__init__.__doc__
print p.show.__doc__
Output:
Jay
Sum = 5
Doc - Inside Class
Doc - __init__ Constructor
Doc - Inside Show
Destructor Deleting object - Jay
Had trouble undestanding this myself. Even after reading the answers here.
To properly understand the __init__ method you need to understand self.
The self Parameter
The arguments accepted by the __init__ method are :
def __init__(self, arg1, arg2):
But we only actually pass it two arguments :
instance = OurClass('arg1', 'arg2')
Where has the extra argument come from ?
When we access attributes of an object we do it by name (or by reference). Here instance is a reference to our new object. We access the printargs method of the instance object using instance.printargs.
In order to access object attributes from within the __init__ method we need a reference to the object.
Whenever a method is called, a reference to the main object is passed as the first argument. By convention you always call this first argument to your methods self.
This means in the __init__ method we can do :
self.arg1 = arg1
self.arg2 = arg2
Here we are setting attributes on the object. You can verify this by doing the following :
instance = OurClass('arg1', 'arg2')
print instance.arg1
arg1
values like this are known as object attributes. Here the __init__ method sets the arg1 and arg2 attributes of the instance.
source: http://www.voidspace.org.uk/python/articles/OOP.shtml#the-init-method
note that self could actually be any valid python identifier. For example, we could just as easily write, from Chris B's example:
class A(object):
def __init__(foo):
foo.x = 'Hello'
def method_a(bar, foo):
print bar.x + ' ' + foo
and it would work exactly the same. It is however recommended to use self because other pythoners will recognize it more easily.
What does self do? What is it meant to be? Is it mandatory?
The first argument of every class method, including init, is always a reference to the current instance of the class. By convention, this argument is always named self. In the init method, self refers to the newly created object; in other class methods, it refers to the instance whose method was called.
Python doesn't force you on using "self". You can give it any name you want. But remember the first argument in a method definition is a reference to the object. Python adds the self argument to the list for you; you do not need to include it when you call the methods.
if you didn't provide self in init method then you will get an error
TypeError: __init___() takes no arguments (1 given)
What does the init method do? Why is it necessary? (etc.)
init is short for initialization. It is a constructor which gets called when you make an instance of the class and it is not necessary. But usually it our practice to write init method for setting default state of the object. If you are not willing to set any state of the object initially then you don't need to write this method.
__init__ is basically a function which will "initialize"/"activate" the properties of the class for a specific object, once created and matched to the corresponding class..
self represents that object which will inherit those properties.
Basically, you need to use the 'self' keyword when using a variable in multiple functions within the same class. As for init, it's used to setup default values incase no other functions from within that class are called.
The 'self' is a reference to the class instance
class foo:
def bar(self):
print "hi"
Now we can create an instance of foo and call the method on it, the self parameter is added by Python in this case:
f = foo()
f.bar()
But it can be passed in as well if the method call isn't in the context of an instance of the class, the code below does the same thing
f = foo()
foo.bar(f)
Interestingly the variable name 'self' is just a convention. The below definition will work exactly the same.. Having said that it is very strong convention which should be followed always, but it does say something about flexible nature of the language
class foo:
def bar(s):
print "hi"
Just a demo for the question.
class MyClass:
def __init__(self):
print('__init__ is the constructor for a class')
def __del__(self):
print('__del__ is the destructor for a class')
def __enter__(self):
print('__enter__ is for context manager')
return self
def __exit__(self, exc_type, exc_value, traceback):
print('__exit__ is for context manager')
def greeting(self):
print('hello python')
if __name__ == '__main__':
with MyClass() as mycls:
mycls.greeting()
$ python3 class.objects_instantiation.py
__init__ is the constructor for a class
__enter__ is for context manager
hello python
__exit__ is for context manager
__del__ is the destructor for a class
In this code:
class Cat:
def __init__(self, name):
self.name = name
def info(self):
print 'I am a cat and I am called', self.name
Here __init__ acts as a constructor for the class and when an object is instantiated, this function is called. self represents the instantiating object.
c = Cat('Kitty')
c.info()
The result of the above statements will be as follows:
I am a cat and I am called Kitty
# Source: Class and Instance Variables
# https://docs.python.org/2/tutorial/classes.html#class-and-instance-variables
class MyClass(object):
# class variable
my_CLS_var = 10
# sets "init'ial" state to objects/instances, use self argument
def __init__(self):
# self usage => instance variable (per object)
self.my_OBJ_var = 15
# also possible, class name is used => init class variable
MyClass.my_CLS_var = 20
def run_example_func():
# PRINTS 10 (class variable)
print MyClass.my_CLS_var
# executes __init__ for obj1 instance
# NOTE: __init__ changes class variable above
obj1 = MyClass()
# PRINTS 15 (instance variable)
print obj1.my_OBJ_var
# PRINTS 20 (class variable, changed value)
print MyClass.my_CLS_var
run_example_func()
Here, the guy has written pretty well and simple: https://www.jeffknupp.com/blog/2014/06/18/improve-your-python-python-classes-and-object-oriented-programming/
Read above link as a reference to this:
self? So what's with that self parameter to all of the Customer
methods? What is it? Why, it's the instance, of course! Put another
way, a method like withdraw defines the instructions for withdrawing
money from some abstract customer's account. Calling
jeff.withdraw(100.0) puts those instructions to use on the jeff
instance.
So when we say def withdraw(self, amount):, we're saying, "here's how
you withdraw money from a Customer object (which we'll call self) and
a dollar figure (which we'll call amount). self is the instance of the
Customer that withdraw is being called on. That's not me making
analogies, either. jeff.withdraw(100.0) is just shorthand for
Customer.withdraw(jeff, 100.0), which is perfectly valid (if not often
seen) code.
init self may make sense for other methods, but what about init? When we call init, we're in the process of creating an object, so how can there already be a self? Python allows us to extend
the self pattern to when objects are constructed as well, even though
it doesn't exactly fit. Just imagine that jeff = Customer('Jeff
Knupp', 1000.0) is the same as calling jeff = Customer(jeff, 'Jeff
Knupp', 1000.0); the jeff that's passed in is also made the result.
This is why when we call init, we initialize objects by saying
things like self.name = name. Remember, since self is the instance,
this is equivalent to saying jeff.name = name, which is the same as
jeff.name = 'Jeff Knupp. Similarly, self.balance = balance is the same
as jeff.balance = 1000.0. After these two lines, we consider the
Customer object "initialized" and ready for use.
Be careful what you __init__
After init has finished, the caller can rightly assume that the
object is ready to use. That is, after jeff = Customer('Jeff Knupp',
1000.0), we can start making deposit and withdraw calls on jeff; jeff is a fully-initialized object.
Python __init__ and self what do they do?
What does self do? What is it meant to be? Is it mandatory?
What does the __init__ method do? Why is it necessary? (etc.)
The example given is not correct, so let me create a correct example based on it:
class SomeObject(object):
def __init__(self, blah):
self.blah = blah
def method(self):
return self.blah
When we create an instance of the object, the __init__ is called to customize the object after it has been created. That is, when we call SomeObject with 'blah' below (which could be anything), it gets passed to the __init__ function as the argument, blah:
an_object = SomeObject('blah')
The self argument is the instance of SomeObject that will be assigned to an_object.
Later, we might want to call a method on this object:
an_object.method()
Doing the dotted lookup, that is, an_object.method, binds the instance to an instance of the function, and the method (as called above) is now a "bound" method - which means we do not need to explicitly pass the instance to the method call.
The method call gets the instance because it was bound on the dotted lookup, and when called, then executes whatever code it was programmed to perform.
The implicitly passed self argument is called self by convention. We could use any other legal Python name, but you will likely get tarred and feathered by other Python programmers if you change it to something else.
__init__ is a special method, documented in the Python datamodel documentation. It is called immediately after the instance is created (usually via __new__ - although __new__ is not required unless you are subclassing an immutable datatype).

Categories