Programmer's Python - Objects Become Classes |
Written by Mike James | ||||
Monday, 04 July 2022 | ||||
Page 3 of 3
How Functions Become MethodsPython has functions, but it doesn’t have anything fundamental that works as a method. Instead when a function is defined as an attribute within a class the way that it works is automatically modified to make it work as a method for the instances the class creates. That is, functions are augmented to become methods. You can see that if you want to use a function as a method all you have to do is convert the method call: myArray.sort(args) into the function call with an extra parameter: sort(myArray,args) In Python this transformation from method to function works in a very direct way. Within the class you create a function attribute in the usual way, but with an extra first parameter, usually called self, which is going to be used to set the instance the function is working with. For example: class myClass: myAttribute=1 def myFunc(self): print(self.myAttribute) myFunc is just a standard function object, i.e. not a method. The first parameter is named self only by convention. You can use any name you like, but be prepared to confuse everyone if you do. The first parameter is used within the function to reference the instance and in this case you can see that it is being used to print myAttribute belonging to the instance. If you call myFunc as an attribute of the myClass object then there is nothing new: myClass.myFunc(myClass) and it prints 1 as you would expect. Notice that you have to explicitly pass a value for self and this is just the object you want the function to operate on. So far so good, but to create a method we need to arrange for the first parameter to be passed the instance automatically. When you call the function on an instance rather than the class then Python does something extra. It takes the reference to myFunc and replaces it with a new object called a “bound method”. This is a special form of function object which roughly corresponds to: def method(args): return myClass.myFunc(myObject,args) That is, on the instance, myObject, the attribute myFunc now references a new auto-generated bound method object which calls the class version of myFunc complete with myObject as the first parameter and whatever other parameters are in use. You can now call myFunc on an instance: myObject=myClass() myObject.myFunc() and this is converted into: myClass.myFunc(myObject) This is how a function becomes a method. When a function attribute is called on an instance the call is converted to a call to the same attribute on the class object with the first parameter set to the instance making the call. That is: myObject.myFunc() automatically becomes: myClass.myFunc(myObject) Notice that this also means that by default all of the instances of a class use the functions defined on the class object as their methods.
A common error is due to not realizing that the self parameter is automatically added to a call to an instance method and mistakenly explicitly supplying it, i.e. calling the method as if it was a function: myObject.myFunc(myObject) If you try this out you get an error message: myObject.myFunc(myObject) TypeError: myFunc() takes 1 positional argument but 2 were given which, like most error messages, doesn’t actually tell you what the problem is. More to the point when you look at it then you have to come to the conclusion that the error message lies! It is quite clear that myFunc takes one argument but “2 were given” is clearly wrong. Only one argument was given so what is going on? Of course, the answer is obvious – the single parameter has been supplied an argument automatically and now it looks as if you are trying to call a function with two parameters. The rule is that when you are writing a method within a class object you include an additional first parameter – usually called self, but when you are calling the method you don’t specify the parameter because the system automatically sets it to the instance you are calling it on. In the class the myFunc is a function object. In an instance of the class myFunc is replaced by a method object. A method object has all of the attributes of a function object plus two that help with the operation of the method:
With these two attributes defined you can think of the call from the instance myObject as: myObject.myFunc.__func__(myObject.__self__, *args, **kwargs) which, in the case of our example, evaluates to: myClass.myFunc(myObject) In book but not in this extract
Summary
Programmer's Python
|
||||
Last Updated ( Tuesday, 16 April 2024 ) |