Programmer's Python - Objects Become Classes
Written by Mike James   
Monday, 09 November 2020
Article Index
Programmer's Python - Objects Become Classes
Instance Attributes
Example

Everything in Python might well be an object, but if this is the case we need some way of creating new custom objects. How  objects become classes and more is explained in this extract from my book, Programmer's Python: Everything is an Object.

Programmer's Python
Everything is an Object

Is now available as a print book: Amazon

pythoncover


Contents

  1. Hello Python World
  2. Variables, Objects and Attributes
  3. The Function Object
      Extract - Function Objects
  4. Scope, Lifetime and Closure
      Extract - Local and Global
  5. Advanced Functions
      Extract -  Decorators 
  6. Class Methods and Constructors
      Extract - Objects Become Classes ***NEW
  7. Inside Class
  8. Metaclass
  9. Advanced Attributes
      Extract - Properties
  10. Custom Attribute Access
      Extract -  Custom Attributes
      Extract -  Default Methods
  11. Single Inheritance
  12. Multiple Inheritance
  13. Class and Type
      Extract - Class
  14. Type Annotation
      Extract - Type Annotation 
  15. More Magic - Operator Overloading

 

Advanced Attributes

 

We used the class keyword to create one off objects in Chapter 2 but this doesn’t solve the problem of what to do if we need tens or even hundreds of copies of an object. In fact class is more a solution to this problem than it is to creating a single one off object.

In this chapter we look at the general idea of an object factory and in particular the object constructor. Python implements what looks like an object constructor that you might find in other class-based languages but it has some interesting differences which might confuse you if you already know a more traditional approach to the problem as found in Java, C++ or C#.

The Classical Constructor

It might help to look first at how class-based languages deal with the problem of creating instances. If you don't know about how class-based languages work just skip to the next section.

In class-based languages, instances of a class are generally created using the constructor which implicitly uses the class definition to manufacture an instance of the class.

For example, in language like Java, C++ or C# you would write:

MyClass myObject = new myClass();

where myClass() is the constructor.

The constructor is a function that returns an instance of the class. 

This is a fact that is often overlooked by programmers in class-based languages because they don't actually have to write anything in the constructor for it to do its job.

That is, an empty or default constructor will automatically do the job of creating an instance. This results in programmers thinking that constructors are really only needed when something has to be initialized or set up in some way.

The idea of a constructor can be extended to the idea of an object factory. An object factory is an object that will create another object – perhaps another instance of its own type or another completely different type.

The idea of a function which creates objects is core to class-based languages and, in fact, to all object-oriented languages and Python in particular.

The Class Object

The class object is another example of a Python callable. The function object is also a Python callable and basically any callable can be treated as a variation on a function object.

You can use the class keyword to create a custom class object as described in Chapter 2. Put simply the class object is an object factory. It creates a new object with the attributes you define.

For example:

class myClass:
    myAttribute=1

creates a new class object with the single attribute. You can now use myClass as if it was a custom object – which it is and it has a single attribute – myAttribute.

For example:

myClass.myAttribute=2

is perfectly valid and it sets the myAttribute to 2 as you would expect.

However, you can also call the myClass object as if it was a function and if you do this, by default it will seem to create a copy of itself – an instance of the class. What happens is a little more subtle and it is important you know how it works but for the moment let’s just see it in action.

For example:

myObject=myClass()
print(myClass.myAttribute)
print(myObject.myAttribute)

If you try this out you will discover that you now have a myClass object and a myObject object and they both have a myAttribute attribute.

It looks as if myObject is a complete copy of myClass but this isn’t the case. In fact myObject is an empty object.

That is its __dict__ is empty and it has no attributes of its own.

When you try to access an attribute on the myObject its local dictionary object is searched i.e. __dict__ and then its class object __dict__ is searched. Every instance object has a __class__ attribute that references the instance class and this allows the system to search the class __dict__ for the attribute.

In this case when you use:

myObject.myAttribute

the system first looks in myObject.__dict__ and when it doesn’t find it then it looks in myObject.__class__.__dict__

To be clear:

when first created an instance of a class shares all of the class’s attributes and has none of its own.

That is when you use:

myObject.myAttribute

you are actually accessing:

myClass.myAttribute

If you know JavaScript you will recognize that the class object is acting as a prototype for the instance object.

You can see that this is true if you try:

myObject=myClass()
print(myClass.myAttribute)
myClass.myAttribute=2
print(myObject.myAttribute)

The final print displays 2 because changing myClass.myAttribute changes the shared attribute.



Last Updated ( Monday, 09 November 2020 )