Page 1 of 3
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.
Everything is an Object
Is now available as a print book: Amazon
- Hello Python World
- Variables, Objects and Attributes
- The Function Object
Extract - Function Objects
- Scope, Lifetime and Closure
Extract - Local and Global
Extract - Closure ***NEW
- Advanced Functions
Extract - Parameters
Extract - Decorators
- Class Methods and Constructors
Extract - Objects Become Classes
- Inside Class
- Advanced Attributes
Extract - Properties
- Custom Attribute Access
Extract - Custom Attributes
Extract - Default Methods
- Single Inheritance
- Multiple Inheritance
- Class and Type
Extract - Class & Type
- Type Annotation
Extract - Type Annotation
- More Magic - Operator Overloading
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.
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.
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.
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:
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:
you are actually accessing:
You can see that this is true if you try:
The final print displays 2 because changing myClass.myAttribute changes the shared attribute.