Hey, Mom! Talking to My Mother #866 - Python- A case for "self" in classes
Hi Mom,
Today. we're back to the content that is my study and not my teaching and lately I have been studying Python.
A few weeks ago in my studies I was curious about the use of "self" in classes. I was pretty sure that it was similar to the use of "this" in the other programs, like Java, to denote the object itself during instantiation (making an instance) of the class.
One of the things I like to do with my blog, now, in the second year is use it as a place to store material that I am studying, and then to aggregate some of that material in a place where people can find it in a search on the subject.
Lots of texts on Python will imply that "self" is required more so than a convention. I prefer "self" for calls to the class object to "this" that is used in other languages, such as Java: THIS KEYWORD. In Java, "this" is a keyword, meaning it is a word reserved to refer to an instance of the class in the constructor and used for initializing variables or referring to members of the class. But unlike Java, in Python, self is set up explicitly in the "constructor" or __init__ method of the class.
I like that what I have collected here both explains "self" a s a convention for referencing an object, but also shows Python creator Guido Van Rossum's remarks on his own blog in response to a proposal to make "self" a reserved keyword in Python.
I know, Mom, and many of my regular readers, this is outside your interest, probably (unless I have new coding readers), but this is my study more often than my teaching, and I have finished my grading for the week, so I can post this one. I have been noodling it for quite some time.
So, this is a good collection of material about the use of "self" and the debate about its use a s a convention rather than a reserved keyword all collected here for your convenience. If you're studying Python and found this through search, leave me a comment.
OUR CONTENT TODAY:
https://pythontips.com/2013/
FROM
The self variable in python explained
Hi there fellas. In this post I am going to teach you about the
self
variable in python. I have seen many beginners struggling to grasp the concept of self
variable. If you are one of them then this post is for you. So lets start by making a class involving the self
variable.
A simple class :
So here is our class:
class Restaurant(object): bankrupt = False def open_branch(self): if not self.bankrupt: print("branch opened")
First let me explain the above code without the technicalities. First of all we make a class Restaurant. Then we assign it a property “bankrupt” which is currently false. After that we assign it a function open_branch which can only occur if “bankrupt” is False which means that the Restaurant has some money.
Making a resturant:
Now that we have made a class for a Restaurant, lets actually make a resturant:
x = Restaurant()
Now x is a Restaurant which has a property bankrupt and a function open_branch. Now we can access the property bankrupt by typing:
x.bankrupt
The above command is same as:
Restaurant().bankrupt
Now you can see that self refers to the bound variable or object. In the first case it was x because we had assigned the Restaurant class to x whereas in the second case it referred to Restaurant(). Now if we have another Restaurant y, self will know to access the bankrupt value of y and not x. For example check this example:
>>> x = Restaurant() >>> x.bankrupt False >>> y = Restaurant() >>> y.bankrupt = True >>> y.bankrupt True >>> x.bankrupt False
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. For example the below code is the same as the above code.
class Restaurant(object): bankrupt = False def open_branch(this): if not this.bankrupt: print("branch opened")
Free Tip:
However self is not a reserved keyword in python it’s just a strong convention. Many people say that why do we have to write self ? Why can’t we have it set automatically like in Java ? Someone also filed a PEP (improvement suggestion) in which he suggested to remove the explicit assignment of self keyword. However Guido Van Rossum (the maker of python) wrote a blogpost in which he told why explicit self has to stay.
I hope you have understood to concept of self. If you have any other questions then feel free to comment. If you liked this post then make sure that you share it on facebook, tweet it on twitter and follow our blog.
You might also like:
) Python socket network programming
*) args and **kwargs in python explained
*) Making a url shortener in python
) Python socket network programming
*) args and **kwargs in python explained
*) Making a url shortener in python
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
FROM
112
|
When objects are instantiated, the object itself is passed into the self parameter.
Because of this, the object’s data is bound to the object. Below is an example of how you might like to visualize what each object’s data might look. Notice how ‘self’ is replaced with the objects name. I'm not saying this example diagram below is wholly accurate but it hopefully with serve a purpose in visualizing the use of self.
The Object is passed into the self parameter so that the object can keep hold of its own data.
Although this may not be wholly accurate, think of the process of instantiating an object like this: When an object is made it uses the class as a template for its own data and methods. Without passing it's own name into the self parameter, the attributes and methods in the class would remain as a general template and would not be referenced to (belong to) the object. So by passing the object's name into the self parameter it means that if 100 objects are instantiated from the one class, they can all keep track of their own data and methods.
See the illustration below:
|
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
FROM
UNDERSTANDING SELF AND __INIT__ METHOD IN PYTHON CLASS.
Reading Time : ~ .
Before understanding the "self" and "__init__" methods in python class, it's very helpful if we have the idea of what is a class and object.
Class :
Class is a set or category of things having some property or attribute in common and differentiated from others by kind, type, or quality.
In technical terms we can say that class is a blue print for individual objects with exact behaviour.
Object :
object is one of instances of the class. which can perform the functionalities which are defined in the class.
self :
self represents the instance of the class. By using the "self" keyword we can access the attributes and methods of the class in python.
__init__ :
"__init__" is a reseved method in python classes. It is known as a constructor in object oriented concepts. This method called when an object is created from the class and it allow the class to initialize the attributes of a class.
How can we use "__init__ " ?
Let's consider that you are creating a NFS game. for that we should have a car. Car can have attributes like "color", "company", "speed_limit" etc. and methods like "change_gear", "start", "accelarate", "move" etc.
class Car(object): """ blueprint for car """ def __init__(self, model, color, company, speed_limit): self.color = color self.company = company self.speed_limit = speed_limit self.model = model def start(self): print("started") def stop(self): print("stopped") def accelarate(self): print("accelarating...") "accelarator functionality here" def change_gear(self, gear_type): print("gear changed") " gear related functionality here"
Lets try to create different types of cars
maruthi_suzuki = Car("ertiga", "black", "suzuki", 60) audi = Car("A6", "red", "audi", 80)
We have created two different types of car objects with the same class. while creating the car object we passed arguments "ertiga", "black", "suzuki", 60 these arguments will pass to "__init__" method to initialize the object.
Here, the magic keyword "self" represents the instance of the class. It binds the attributes with the given arguments.
Usage of "self" in class to access the methods and attributes
Case: Find out the cost of a rectangular field with breadth(b=120), length(l=160). It costs x (2000) rupees per 1 square unit
class Rectange: def __init__(self, length, breadth, unit_cost=0): self.length = length self.breadth = breadth self.unit_cost = unit_cost def get_perimeter(self): return 2 * (self.length + self.breadth) def get_area(self): return self.length * self.breadth def calculate_cost(self): area = self.get_area() return area * self.cost # breadth = 120 cm, length = 160 cm, 1 cm^2 = Rs 2000 r = Rectangle(160, 120, 2000) print("Area of Rectangle: %s cm^2" % (r.get_area())) print("Cost of rectangular field: Rs. %s ", %(r.calculate_cost()))
As we already discussed "self" represents the same object or instance of the class. If you see, inside the method "get_area" we have used "self.length" to get the value of the attribute "length". attribute "length" is bind to the object(instance of the class) at the time of object creation. "self" represents the object inside the class. "self" works just like "r" in the statement "r = Rectangle(160, 120, 2000)". If you see the method structure "def get_area(self): " we have used "self" as a parameter in the method because whenever we call the method the object (instance of class) automatically passes as a first argument along with other argumets of the method.If no other arguments are provided only "self" is passed to the method. That's the reason we use "self" to call the method inside the class("self.get_area()"). we use object( instance of class) to call the method outside of the class definition("r.get_area()"). "r" is the instance of the class, when we call method "r.get_area()" the instance "r" is passed as as first argument in the place of self.
r = Rectangle(160, 120, 2000)
Note: "r" is the representation of the object outside of the class and "self" is the representation of the object inside the class.
Note: "r" is the representation of the object outside of the class and "self" is the representation of the object inside the class.
for more details please visit python documentation
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
SUNDAY, OCTOBER 26, 2008
Why explicit self has to stay
Bruce Eckel has blogged about a proposal to remove 'self' from the formal parameter list of methods. I'm going to explain why this proposal can't fly.
Bruce's Proposal
Bruce understands that we still need a way to distinguish references to instance variables from references to other variables, so he proposes to make 'self' a keyword instead. Consider a typical class with one method, for example:
Why Bruce's Proposal Can't Work
Let me first bring up a few typical arguments that are brought in against Bruce's proposal.
There's a pretty good argument to make that requiring explicit 'self' in the parameter list reinforces the theoretical equivalency between these two ways of calling a method, given that 'foo' is an instance of 'C':
Another argument for keeping explicit 'self' in the parameter list is the ability to dynamically modify a class by poking a function into it, which creates a corresponding method. For example, we could create a class that is completely equivalent to 'C' above as follows:
I suppose that Bruce doesn't particularly care about the former equivalency. I agree that it's more of theoretical importance. The only exception I can think of is the old idiom for calling a super method. However, this idiom is pretty error-prone (exactly due to the requirement to explicitly pass 'self'), and that's why in Python 3000 I'm recommending the use of 'super()' in all cases.
Bruce can probably think of a way to make the second equivalency work -- there are some use cases where this is really important. I don't know how much time Bruce spent thinking about how to implement his proposal, but I suppose he is thinking along the lines of automatically adding an extra formal parameter named 'self' to all methods defined directly inside a class (I have to add 'directly' so that functions nested inside methods are exempted from this automatism). This way the first equivalency can be made to hold still.
However, there's one situation that I don't think Bruce can fix without adding some kind of ESP to the compiler: decorators. This I believe is the ultimate downfall of Bruce's proposal.
When a method definition is decorated, we don't know whether to automatically give it a 'self' parameter or not: the decorator could turn the function into a static method (which has no 'self'), or a class method (which has a funny kind of self that refers to a class instead of an instance), or it could do something completely different (it's trivial to write a decorator that implements '@classmethod' or '@staticmethod' in pure Python). There's no way without knowing what the decorator does whether to endow the method being defined with an implicit 'self' argument or not.
I reject hacks like special-casing '@classmethod' and '@staticmethod'. I also don't think it would be a good idea to automagically decide whether something is supposed to be a class method, instance method, or static method from inspection of the body alone (as someone proposed in the comments on Bruce's proposal): this makes it harder to tell how it should be called from the 'def' heading alone.
In the comments I saw some pretty extreme proposals to save Bruce's proposal, but generally at the cost of making the rules harder to follow, or requiring deeper changes elsewhere to the language -- making it infinitely harder to accept the proposal as something we could do in Python 3.1. For 3.1, by the way, the rule will be once again that new features are only acceptable if they remain backwards compatible.
The one proposal that has something going for it (and which can trivially be made backwards compatible) is to simply accept
inside a class as syntactic sugar for
I see no reason with this proposal to make 'self' a reserved word or to require that the prefix name be exactly 'self'. It would be easy enough to allow this for class methods as well:
I could go on more, but it's a nice sunny Sunday morning, and I have other plans... :-)
Bruce's Proposal
Bruce understands that we still need a way to distinguish references to instance variables from references to other variables, so he proposes to make 'self' a keyword instead. Consider a typical class with one method, for example:
class C: def meth(self, arg): self.val = arg return self.valUnder Bruce's proposal this would become:
class C: def meth(arg): # Look ma, no self! self.val = arg return self.valThat's a saving of 6 characters per method. However, I don't believe Bruce proposes this so that he has to type less. I think he's more concerned about the time wasted by programmers (presumably coming from other languages) where the 'self' parameter doesn't need to be specified, and who occasionally forget it (even though they know better -- habit is a powerful force). It's true that omitting 'self' from the parameter list tends to lead to more obscure error messages than forgetting to type 'self.' in front of an instance variable or method reference. Perhaps even worse (as Bruce mentions) is the error message you get when the method is declared correctly but the call has the wrong number of arguments, like in this example given by Bruce:
Traceback (most recent call last): File "classes.py", line 9, in obj.m2(1) TypeError: m2() takes exactly 3 arguments (2 given)I agree that this is confusing, but I would rather fix this error message without changing the language.
Why Bruce's Proposal Can't Work
Let me first bring up a few typical arguments that are brought in against Bruce's proposal.
There's a pretty good argument to make that requiring explicit 'self' in the parameter list reinforces the theoretical equivalency between these two ways of calling a method, given that 'foo' is an instance of 'C':
foo.meth(arg) == C.meth(foo, arg)
Another argument for keeping explicit 'self' in the parameter list is the ability to dynamically modify a class by poking a function into it, which creates a corresponding method. For example, we could create a class that is completely equivalent to 'C' above as follows:
# Define an empty class: class C: pass # Define a global function: def meth(myself, arg): myself.val = arg return myself.val # Poke the method into the class: C.meth = methNote that I renamed the 'self' parameter to 'myself' to emphasize that (syntactically) we're not defining a method here. Now instances of C have a method with one argument named 'meth' that works exactly as before. It even works for instances of C that were created before the method was poked into the class.
I suppose that Bruce doesn't particularly care about the former equivalency. I agree that it's more of theoretical importance. The only exception I can think of is the old idiom for calling a super method. However, this idiom is pretty error-prone (exactly due to the requirement to explicitly pass 'self'), and that's why in Python 3000 I'm recommending the use of 'super()' in all cases.
Bruce can probably think of a way to make the second equivalency work -- there are some use cases where this is really important. I don't know how much time Bruce spent thinking about how to implement his proposal, but I suppose he is thinking along the lines of automatically adding an extra formal parameter named 'self' to all methods defined directly inside a class (I have to add 'directly' so that functions nested inside methods are exempted from this automatism). This way the first equivalency can be made to hold still.
However, there's one situation that I don't think Bruce can fix without adding some kind of ESP to the compiler: decorators. This I believe is the ultimate downfall of Bruce's proposal.
When a method definition is decorated, we don't know whether to automatically give it a 'self' parameter or not: the decorator could turn the function into a static method (which has no 'self'), or a class method (which has a funny kind of self that refers to a class instead of an instance), or it could do something completely different (it's trivial to write a decorator that implements '@classmethod' or '@staticmethod' in pure Python). There's no way without knowing what the decorator does whether to endow the method being defined with an implicit 'self' argument or not.
I reject hacks like special-casing '@classmethod' and '@staticmethod'. I also don't think it would be a good idea to automagically decide whether something is supposed to be a class method, instance method, or static method from inspection of the body alone (as someone proposed in the comments on Bruce's proposal): this makes it harder to tell how it should be called from the 'def' heading alone.
In the comments I saw some pretty extreme proposals to save Bruce's proposal, but generally at the cost of making the rules harder to follow, or requiring deeper changes elsewhere to the language -- making it infinitely harder to accept the proposal as something we could do in Python 3.1. For 3.1, by the way, the rule will be once again that new features are only acceptable if they remain backwards compatible.
The one proposal that has something going for it (and which can trivially be made backwards compatible) is to simply accept
def self.foo(arg): ...
inside a class as syntactic sugar for
def foo(self, arg): ...
I see no reason with this proposal to make 'self' a reserved word or to require that the prefix name be exactly 'self'. It would be easy enough to allow this for class methods as well:
@classmethod def cls.foo(arg): ...Now, I'm not saying that I like this better than the status quo. But I like it a lot better than Bruce's proposal or the more extreme proposals brought up in the comments to his blog, and it has the great advantage that it is backward compatible, and can be evolved into a PEP with a reference implementation without too much effort. (I think Bruce would have found out the flaws in his own proposal if he had actually gone through the effort of writing a solid PEP for it or trying to implement it.)
I could go on more, but it's a nice sunny Sunday morning, and I have other plans... :-)
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Reflect and connect.
Have someone give you a kiss, and tell you that I love you, Mom.
I miss you so very much, Mom.
Talk to you tomorrow, Mom.
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
- Days ago = 868 days ago
- Bloggery committed by chris tower - 1711.19 -10:10
NEW (written 1708.27) NOTE on time: I am now in the same time zone as Google! So, when I post at 10:10 a.m. PDT to coincide with the time of your death, Mom, I am now actually posting late, so it's really 1:10 p.m. EDT. But I will continue to use the time stamp of 10:10 a.m. to remember the time of your death, Mom. I know this only matters to me, and to you, Mom.
38 comments: