; Date: Thu Sep 26 2019
Python classes allow programmers to define new data types to use in their programs. They act like a blueprint with which a program creates objects. Objects can contain both methods and attributes, giving us a useful higher-level abstraction over the built-in Python data types.
Classes in Python support typical object-oriented programming features like inheritance, deriving a class definition from one or more base classes, and overriding methods and attributes inherited from a base class. But unlike other languages, the implementation fits the dynamic nature of Python programming.
What is a Python class, and how do we use them?
A Python class definition is a series of statements that define the Python class.
class ClassName: Statement 1 Statement 2 ... Statement N
The statements are usually function definitions but can be variable assignments. It is helpful to think of a Python class as a blueprint for constructing instances of an object.
To use a class in python code, we must create an instance of the class like so:
X = ClassName()
While creating a new instance the special function
__init__ is called. It receives an argument list containing the parameters passed to the constructor.
class Dog(Animal): kind = 'canine' def __init__(self, name) self.name = name
In this Python class example, we have a class Dog that inherits from Animal.
The first parameter of every method defined in a python class is a reference to the object. In Python the convention is to name this variable
self, and it has the same purpose as the
this variable used in other languages.
Python namespaces and scopes
Before we get too far into Class definitions in Python, we must first discuss Python Namespaces.
A namespace is a mapping from names to objects, which probably sounds hopelessly obtuse. The object is the actual thing, the chunk of data, while the name is the reference to that thing. Consider:
mydog = Dog('fido')
The variable name
mydog is recorded as a name whereas the chunk of data that is the instance of the
Dog class is the object.
Some examples of Namespaces are:
- The set of built-in names
- The global names in a module
- The local names in a function execution
The same name can be defined in two or more namespaces. This means each namespace is what it sounds like - a space in which to store names.
A scope is a textual region in a Python program where a given namespace is directly accessible. What that means is that in a given scope, an unqualified name is searched for starting in the given namespace.
Python classes and namespaces
When a Python class is defined, a new namespace is created. That namespace is used as the local scope, meaning that variable assignments and function definitions create names in that namespace.
Python class objects
When the Python class definition ends, a class object is created. The previous local scope is reinstated, and the class object is registered in that namespace using the class name.
Class objects and instance variables
When we create an instance of a class Python hammers out a chunk of data using the blueprint in the class object. The data stored for an instance is, of course, not stored in the class object. Instead, we have two objects:
- The class object stores the attributes and methods common to all instances of a class
- The instance stores the data unique to that instance
In the example above the kind attribute is stored in the class object, and is shared by all Dog instances. The name attribute is stored in the instance object and is unique to that instance.
Python does not have private attributes - avoiding name conflicts
In many programming languages, the Class implementation supports hidden data or hidden methods. These hidden things are, as expected, cannot be used by code outside the object. This creates some safety since a programmer can use this hidden data or methods with the assurance that no other code can mess with those things.
One issue is whether there are conflicting names when deriving a class from another class.
Since Python does not support any kind of data hiding it is necessary to follow a convention to avoid conflicts.
The convention most Python programmers follow is that a name prefixed with an underscore (e.g.
_foo) is to be treated as a non-public part of the API of the class. Users of that class are to expect
_foo attributes can change at any time, and should therefore not be used.
The Python language takes this a step further. For any name prefixed by two underscores (e.g.
__private), it is textually replaced with the name
Python's this is self
In most languages, a variable named this is always available and references the instance. So this.name would reference the name attribute in the instance.
In Python, there is no such predefined object. However, every method defined in a class receives as its first argument a reference to the instance object. By convention Python, programmers call this parameter self.
class Bag: def __init__(self): self.data =  def add(self, x): self.data.append(x)
In this case, data is an attribute containing a Python array. The add method adds entries to that array. In both cases, the data array is stored in self making it an instance variable.