Just like str, int, and dict, functions are also objects in Python. Find out how we can take advantage of this feature to write more flexible code.
You’ve probably heard the saying that everything is an object in Python — one of the most popular…
One of the most powerful features of Python is that everything is an object, including functions. Functions in Python are first-class objects.
This broadly means, that functions in Python:
- have types
- can be sent as arguments to another function
- can be used in expression
- can become part of various data…
4 minute read • Python 3.7—3.10
Watch as video
03:49
Sign in to your Python Morsels account to save your screencast settings.
Don't have an account yet? Sign up here.
In Python, everything is an object.
Classes are objects
We have a class called Product
:
class Product:
unknown_price = "Ask for details"
def __init__[self, name, price=None]:
self.name = name
self.price = price
def display_price[self]:
if self.price is None:
return self.unknown_price
return f"{self.price:.2f}"
And we have a variable called
duck
that points to an instance of this Product
class:
>>> duck = Product["duck"]
>>> duck
Variables point to objects, and class instances are objects.
But classes are also objects. So, we can point a variable to a class:
We now have a variable my_class
pointing to the Product
class:
>>> my_class
And in fact, Product
is also just a variable that points to the Product
class:
>>> Product
So anything that we could do with Product
, we could do with my_class
. For example, we could look-up an attribute on the Product
class by accessing either one of these two variables:
>>> my_class.unknown_price
'Ask for details'
>>> Product.unknown_price
'Ask for details'
Or we could call the my_class
variable:
>>> duck = my_class["duck"]
Calling my_class
does the same thing as calling the Product
class. What do you get when you call a class? You get
an instance of that class!
>>> duck
So while class instances are objects, classes are also objects. You can point variables to either class instances or classes.
Modules are objects
Modules are objects too.
So we can point variables to module objects:
>>> import math
>>> silly_math = math
We've imported the math
module and pointed the
silly_math
variable to the math
module object:
>>> silly_math
And if we change the answer
attribute on silly_math
:
>>> silly_math.answer = 42
This will add a new attribute to the math
module object:
Meaning math.answer
is now 42
also:
This was possible because modules are mutable objects, meaning you can add attributes to them and you can update attributes on them.
If we take math.pi
[already defined in math
module] and set it to 3
:
>>> math.pi
3.141592653589793
>>> math.pi = 3
>>> math.pi
3
math.pi
will now be 3
everywhere in our current Python process.
Note that this is a bad idea. You really shouldn't add or update attributes in other modules after you've imported them, but it's possible to do because modules are objects in Python and they're mutable objects, meaning they can be changed.
Functions are objects
Functions are even objects in Python.
We have a function called
greet
:
>>> def greet[name="world"]:
... """Greet a user, or the whole world."""
... print["Hello", name]
...
The one thing you normally do with a function is call it.
This function greet
can be called with one argument or with no arguments:
>>> greet[]
Hello world
>>> greet["Trey"]
Hello Trey
Because functions are objects, we could point another variable, f
, to our function object:
The variable f
points to the greet
function now:
>>> f
That means anything we could do with greet
, we can do with f
:
Both of these variables point to the same function object.
Just like modules, classes, and class instances, functions have attributes.
There is a __defaults__
attribute that Python adds to every function. This attribute represents the default values for all arguments that that function might accept:
>>> greet.__defaults__
['world',]
That __defaults__
attribute points to a tuple that has the string world
in it, meaning if this function is called without its first argument, we'll see Hello world
:
If we wanted
to be devious, we could assign the __defaults__
attribute to a different tuple:
>>> greet.__defaults__ = ['Trey',]
So if we call greet now, it's now going to say Hello Trey
, rather than Hello world
:
This is possible to do because functions are objects, meaning we can point other variables to them, and since they're mutable objects, we can even update the attributes that exist on functions.
Summary
In Python, everything is an object. Classes are objects, instances of classes are objects, modules are objects, and functions are objects.
Anything that you can point a variable to is an object.
Series: Overlooked Fundamentals
These topics are commonly overlooked by new Python programmers.
To track your progress on this Python Morsels topic trail, sign in or sign up.
✕
↑
A Python Tip Every Week
Need to fill-in gaps in your Python skills? I send weekly emails designed to do just that.