Python offers itself not only as a popular scripting language, but also supports the object-oriented programming paradigm. Classes describe data and provide methods to manipulate that data, all encompassed under a single object. Furthermore, classes allow for abstraction by separating concrete implementation details from abstract representations of data.
Code utilizing classes is generally easier to read, understand, and maintain.
Introduction to classes
A class, functions as a template that defines the basic characteristics of a particular object. Here's an example:
There are a few things to note when looking at the above example.
- The class is made up of attributes (data) and methods (functions).
- Attributes and methods are simply defined as normal variables and functions.
- As noted in the corresponding docstring, the
__init__()method is called the initializer. It's equivalent to the constructor in other object oriented languages, and is the method that is first run when you create a new object, or new instance of the class.
- Attributes that apply to the whole class are defined first, and are called class attributes.
- Attributes that apply to a specific instance of a class (an object) are called instance attributes. They are generally defined inside
__init__(); this is not necessary, but it is recommended (since attributes defined outside of
__init__()run the risk of being accessed before they are defined).
- Every method, included in the class definition passes the object in question as its first parameter. The word
selfis used for this parameter (usage of
selfis actually by convention, as the word
selfhas no inherent meaning in Python, but this is one of Python's most respected conventions, and you should always follow it).
- Those used to object-oriented programming in other languages may be surprised by a few things. One is that Python has no real concept of
privateelements, so everything, by default, imitates the behavior of the C++/Java
publickeyword. For more information, see the "Private Class Members" example on this page.
- Some of the class's methods have the following form:
__functionname__(self, other_stuff). All such methods are called "magic methods" and are an important part of classes in Python. For instance, operator overloading in Python is implemented with magic methods. For more information, see the relevant documentation.
Now let's make a few instances of our
We currently have three
We can access the attributes of the class from each instance using the dot operator
. Note again the difference between class and instance attributes:
We can execute the methods of the class using the same dot operator
Inheritance in Python is based on similar ideas used in other object oriented languages like Java, C++ etc. A new class can be derived from an existing class as follows.
BaseClass is the already existing (parent) class, and the
DerivedClass is the new (child) class that inherits (or subclasses) attributes from
BaseClass. Note: As of Python 2.2, all classes implicitly inherit from the
object class, which is the base class for all built-in types.
We define a parent
Rectangle class in the example below, which implicitly inherits from
Rectangle class can be used as a base class for defining a
Square class, as a square is a special case of rectangle.
Square class will automatically inherit all attributes of the
Rectangle class as well as the object class.
super() is used to call the
__init__() method of
Rectangle class, essentially calling any overridden method of the base class. Note: in Python 3,
super() does not require arguments.
Derived class objects can access and modify the attributes of its base classes:
Built-in functions that work with inheritance
issubclass(DerivedClass, BaseClass): returns
DerivedClass is a subclass of the
isinstance(s, Class): returns
True if s is an instance of
Class or any of the derived classes of
Bound, unbound, and static methods
The idea of bound and unbound methods was removed in Python 3. In Python 3 when you declare a method within a class, you are using a
def keyword, thus creating a function object. This is a regular function, and the surrounding class works as its namespace. In the following example we declare method
f within class
A, and it becomes a function
In Python 2 the behavior was different: function objects within the class were implicitly replaced with objects of type
instancemethod, which were called unbound methods because they were not bound to any particular class instance. It was possible to access the underlying function using
The latter behaviors are confirmed by inspection - methods are recognized as functions in Python 3, while the distinction is upheld in Python 2.
In both versions of Python function/method
A.f can be called directly, provided that you pass an instance of class
A as the first argument.
a is an instance of class
A, what is
a.f then? Well, intuitively this should be the same method
f of class
A, only it should somehow "know" that it was applied to the object
a – in Python this is called method bound to
The nitty-gritty details are as follows: writing
a.f invokes the magic
__getattribute__ method of
a, which first checks whether
a has an attribute named
f (it doesn't), then checks the class
A whether it contains a method with such a name (it does), and creates a new object
m of type
method which has the reference to the original
m.__func__, and a reference to the object
m.__self__. When this object is called as a function, it simply does the following:
m(...) => m.__func__(m.__self__, ...). Thus this object is called a bound method because when invoked it knows to supply the object it was bound to as the first argument. (These things work same way in Python 2 and 3).
Finally, Python has class methods and static methods – special kinds of methods. Class methods work the same way as regular methods, except that when invoked on an object they bind to the class of the object instead of to the object. Thus
m.__self__ = type(a). When you call such bound method, it passes the class of
a as the first argument. Static methods are even simpler: they don't bind anything at all, and simply return the underlying function without any transformations.
Note that class methods are bound to the class even when accessed on the instance:
It is worth noting that at the lowest level, functions, methods, staticmethods, etc. are actually descriptors that invoke
__set__ and optionally
__del__ special methods. For more details on classmethods and staticmethods:
- What is the difference between @staticmethod and @classmethod in Python?
- Meaning of @classmethod and @staticmethod for beginner?
Class and instance variables
Instance variables are unique for each instance, while class variables are shared by all instances.
Class variables can be accessed on instances of this class, but assigning to the class attribute will create an instance variable which shadows the class variable
Note that mutating class variables from instances can lead to some unexpected consequences.
Class composition allows explicit relations between objects. In this example, people live in cities that belong to countries. Composition allows people to access the number of all people living in their country:
Class methods: alternate initializers
Class methods present alternate ways to build instances of classes. To illustrate, let's look at an example.
Let's suppose we have a relatively simple
It might be handy to have a way to build instances of this class specifying a full name instead of first and last name separately. One way to do this would be to have
last_name be an optional parameter, and assuming that if it isn't given, we passed the full name in:
However, there are two main problems with this bit of code:
last_nameare now misleading, since you can enter a full name for
first_name. Also, if there are more cases and/or more parameters that have this kind of flexibility, the if/elif/else branching can get annoying fast.
Not quite as important, but still worth pointing out: what if
first_namedoesn't split into two or more things via spaces? We have yet another layer of input validation and/or exception handling...
Enter class methods. Rather than having a single initializer, we will create a separate initializer, called
from_full_name, and decorate it with the (built-in)
cls instead of
self as the first argument to
from_full_name. Class methods are applied to the overall class, not an instance of a given class (which is what
self usually denotes). So, if
cls is our
Person class, then the returned value from the
from_full_name class method is
Person(first_name, last_name, age), which uses
__init__ to create an instance of the
Person class. In particular, if we were to make a subclass
from_full_name would work in the
Employee class as well.
To show that this works as expected, let's create instances of
Person in more than one way without the branching in
Default values for instance variables
If the variable contains a value of an immutable type (e.g. a string) then it is okay to assign a default value like this
One needs to be careful when initializing mutable objects such as lists in the constructor. Consider the following example:
This behavior is caused by the fact that in Python default parameters are bound at function execution and not at function declaration. To get a default instance variable that's not shared among instances, one should use a construct like this:
Descriptors and Dotted Lookups
Descriptors are objects that are (usually) attributes of classes and that have any of
__delete__ special methods.
Data Descriptors have any of
These can control the dotted lookup on an instance, and are used to implement functions,
property. A dotted lookup (e.g. instance
foo of class
Foo looking up attribute
bar - i.e.
foo.bar) uses the following algorithm:
baris looked up in the class,
Foo. If it is there and it is a Data Descriptor, then the data descriptor is used. That's how
propertyis able to control access to data in an instance, and instances cannot override this. If a Data Descriptor is not there, then
baris looked up in the instance
__dict__. This is why we can override or block methods being called from an instance with a dotted lookup. If
barexists in the instance, it is used. If not, we then
look in the class
bar. If it is a Descriptor, then the descriptor protocol is used. This is how functions (in this context, unbound methods),
staticmethodare implemented. Else it simply returns the object there, or there is an
Listing All Class Members
dir() function can be used to get a list of the members of a class:
It is common to look only for "non-magic" members. This can be done using a simple comprehension that lists members with names not starting with
Classes can define a
__dir__() method. If that method exists calling
dir() will call
__dir__(), otherwise Python will try to create a list of members of the class. This means that the dir function can have unexpected results. Two quotes of importance from the official python documentation:
If the object does not provide dir(), the function tries its best to gather information from the object’s dict attribute, if defined, and from its type object. The resulting list is not necessarily complete, and may be inaccurate when the object has a custom getattr().
Note: Because dir() is supplied primarily as a convenience for use at an interactive prompt, it tries to supply an interesting set of names more than it tries to supply a rigorously or consistently defined set of names, and its detailed behavior may change across releases. For example, metaclass attributes are not in the result list when the argument is a class.
In this case, "monkey patching" means adding a new variable or method to a class after it's been defined. For instance, say we defined class
But now we want to add another function later in the code. Suppose this function is as follows.
But how do we add this as a method in
A? That's simple we just essentially place that function into
A with an assignment statement.
Why does this work? Because functions are objects just like any other object, and methods are functions that belong to the class.
get_num shall be available to all existing (already created) as well to the new instances of
These additions are available on all instances of that class (or its subclasses) automatically. For example:
Note that, unlike some other languages, this technique does not work for certain built-in types, and it is not considered good style.
Python uses the C3 linearization algorithm to determine the order in which to resolve class attributes, including methods. This is known as the Method Resolution Order (MRO).
Here's a simple example:
Now if we instantiate FooBar, if we look up the foo attribute, we see that Foo's attribute is found first
Here's the MRO of FooBar:
It can be simply stated that Python's MRO algorithm is
- Depth first (e.g.
- a shared parent (
object) is blocked by a child (
- no circular relationships allowed.
That is, for example, Bar cannot inherit from FooBar while FooBar inherits from Bar.
For a comprehensive example in Python, see the wikipedia entry.
Another powerful feature in inheritance is
super. super can fetch parent classes features.
Multiple inheritance with init method of class, when every class has own init method then we try for multiple ineritance then only init method get called of class which is inherit first.
for below example only Foo class init method getting called Bar class init not getting called
But it doesn't mean that Bar class is not inherit. Instance of final FooBar class is also instance of Bar class and Foo class.
New-style vs. old-style classes
New-style classes were introduced in Python 2.2 to unify classes and types. They inherit from the top-level
object type. A new-style class is a user-defined type, and is very similar to built-in types.
Old-style classes do not inherit from
object. Old-style instances are always implemented with a built-in
In Python 3, old-style classes were removed.
New-style classes in Python 3 implicitly inherit from
object, so there is no need to specify
Python classes support properties, which look like regular object variables, but with the possibility of attaching custom behavior and documentation.
The object's of class
MyClass will appear to have have a property
.string, however it's behavior is now tightly controlled:
As well as the useful syntax as above, the property syntax allows for validation, or other augmentations to be added to those attributes. This could be especially useful with public APIs - where a level of help should be given to the user.
Another common use of properties is to enable the class to present 'virtual attributes' - attributes which aren't actually stored but are computed only when requested.
A singleton is a pattern that restricts the instantiation of a class to one instance/object. For more info on python singleton design patterns, see here.
Another method is to decorate your class. Following the example from this answer create a Singleton class:
To use you can use the