Programmer's Python - Objects Become Classes
Written by Mike James   
Monday, 04 July 2022
Article Index
Programmer's Python - Objects Become Classes
Instance Attributes
Functions Become Methods

How Functions Become Methods

Python 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.


This setting of the self parameter to the instance is usually called binding a function to an instance to create a method.

class4

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:

  • __self__ (read only) is the instance, i.e. myObject in this case

  • __func__ (read only) is the unmodified function object, i.e. myClass.myFunc in this case

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

  • Early Dynamic Binding
  • Method Attributes
  • Other Bindings
  • The Initializer __init__Multiple Constructors
  • Class for Methods, Instance for Data

Summary

  • Unlike in other languages, in Python a class is an object.

  • A class object is a callable, which means it can be called like a function.

  • When called as a function a class returns an instance.

  • At its simplest, an instance has no attributes. Any attributes you try to access on the instance are resolved by attributes on the class object.

  • If you assign to an attribute then it is created as an instance attribute.

  • Function attributes defined on the class object are converted into method objects when accessed via an instance.

  • Methods call the function object using self, the instance, as the first parameter. What this means is that you write function attributes with an explicit self parameter, but when you call a method you do not specify self.

  • Methods are bound to their instance when first accessed. This is a form of early binding.

  • In addition to instance methods, you can also create static and class methods.

  • The initalizer __init__ can be used to add attributes to an instance and to initialize them.

  • You can create multiple constructors using class methods.

  • In Python it makes sense to place all methods in the class body and all data attributes in the __init__. This allows methods to be shared by all instances and data to be unique to each instance.

Programmer's Python
Everything is an Object
Second Edition

Is now available as a print book: Amazon

pythonObject2e360

Contents

  1. Get Ready For The Python Difference
  2. Variables, Objects and Attributes
  3. The Function Object
  4. Scope, Lifetime and Closure
      Extract 1: Local and Global ***NEW!
  5. Advanced Functions
  6. Decorators
  7. Class, Methods and Constructors
      Extract 1: Objects Become Classes 
  8. Inside Class
  9. Meeting Metaclasses
  10. Advanced Attributes
  11. Custom Attribute Access
  12. Single Inheritance
  13. Multiple Inheritance
  14. Class and Type
  15. Type Annotation
  16. Operator Overloading
  17. Python In Visual Studio Code

 Extracts from the first edition

<ASIN:1871962749>

<ASIN:1871962595>

<ASIN:1871962765>

Related Articles

Programmer's Python Data - Comprehensions

Creating The Python UI With Tkinter

Creating The Python UI With Tkinter - The Canvas Widget

The Python Dictionary

Arrays in Python

Advanced Python Arrays - Introducing NumPy

espbook

 

Comments




or email your comment to: comments@i-programmer.info

To be informed about new articles on I Programmer, sign up for our weekly newsletter, subscribe to the RSS feed and follow us on Twitter, Facebook or Linkedin.



Last Updated ( Tuesday, 16 April 2024 )