Update: You can find a newer version of this article on Python Morsels.
If you search course curriculum I’ve written, you’ll often find phrases like “zip
function”, “enumerate
function”, and “list
function”.
Those terms are all technically misnomers.
When I use terms like “the bool
function” and “the str
function” I’m incorrectly implying that bool
and str
are functions.
But these aren’t functions: they’re classes!
I’m going to explain why this confusion between classes and functions happens in Python and then explain why this distinction often doesn’t matter.
Class or function?
When I’m training a new group of Python developers, there’s group activity we often do: the class or function game.
In the class or function game, we take something that we “call” (using parenthesis: ()
) and we guess whether it’s a class or a function.
For example:
- We can call
zip
with a couple iterables and we get another iterable back, so iszip
a class or a function? - When we call
len
, are we calling a class or a function? - What about
int
: when we writeint('4')
are we calling a class or a function?
Python’s zip
, len
, and int
are all often guessed to be functions, but only one of these is really a function:
1 2 3 4 5 6 |
|
While len
is a function, zip
and int
are classes.
The reversed
, enumerate
, range
, and filter
“functions” also aren’t really functions:
1 2 3 4 5 6 7 8 |
|
After playing the class or function game, we always discuss callables, and then we discuss the fact that we often don’t care whether something is a class or a function.
What’s a callable?
A callable is anything you can call, using parenthesis, and possibly passing arguments.
All three of these lines involve callables:
1 2 3 |
|
We don’t know what something
, AnotherThing
, and something_else
do: but we know they’re callables.
We have a number of callables in Python:
- Functions are callables
- Classes are callables
- Methods (which are functions that hang off of classes) are callables
- Instances of classes can even be turned into callables
Callables are a pretty important concept in Python.
Classes are callables
Functions are the most obvious callable in Python. Functions can be “called” in every programming language. A class being callable is a bit more unique though.
In JavaScript we can make an “instance” of the Date
class like this:
1 2 |
|
In JavaScript the class instantiation syntax (the way we create an “instance” of a class) involves the new
keyword.
In Python we don’t have a new
keyword.
In Python we can make an “instance” of the datetime
class (from datetime
) like this:
1 2 |
|
In Python, the syntax for instantiating a new class instance is the same as the syntax for calling a function.
There’s no new
needed: we just call the class.
When we call a function, we get its return value. When we call a class, we get an “instance” of that class.
We use the same syntax for constructing objects from classes and for calling functions: this fact is the main reason the word “callable” is such an important part of our Python vocabulary.
Disguising classes as functions
There are many classes-which-look-like-functions among the Python built-ins and in the Python standard library.
I sometimes explain decorators (an intermediate-level Python concept) as “functions which accept functions and return functions”.
But that’s not an entirely accurate explanation. There are also class decorators: functions which accept classes and return classes. And there are also decorators which are implemented using classes: classes which accept functions and return objects.
A better explanation of the term decorators might be “callables which accept callables and return callables” (still not entirely accurate, but good enough for our purposes).
Python’s property decorator seems like a function:
1 2 3 4 5 6 7 8 9 10 |
|
But it’s a class:
1 2 |
|
The classmethod
and staticmethod
decorators are also classes:
1 2 3 4 |
|
What about context managers, like suppress and redirect_stdout from the contextlib
module?
These both use the snake_case naming convention, so they seem like functions:
1 2 3 4 5 6 7 8 9 10 |
|
But they’re actually implemented using classes, despite the snake_case
naming convention:
1 2 3 4 |
|
Decorators and context managers are just two places in Python where you’ll often see callables which look like functions but aren’t. Whether a callable is a class or a function is often just an implementation detail.
It’s not really a mistake to refer to property
or redirect_stdout
as functions because they may as well be functions.
We can call them, and that’s what we care about.
Callable objects
Python’s “call” syntax, those (...)
parenthesis, can create a class instance or call a function.
But this “call” syntax can also be used to call an object.
Technically, everything in Python “is an object”:
1 2 3 4 5 6 |
|
But we often use the term “object” to imply that we’re working with an instance of a class (by instance of a class I mean “the thing you get back when you call a class”).
There’s a partial function which lives in the functools
module, which can “partially evaluate” a function by storing arguments to be used when calling the function later.
This is often used to make Python look a bit more like a functional programming language:
1 2 3 4 |
|
I said above that Python has “a partial
function”, which is both true and false.
While the phrase “a partial
function” makes sense, the partial
callable isn’t implemented using a function.
1 2 |
|
The Python core developers could have implemented partial
as a function, like this:
1 2 3 4 5 6 |
|
But instead they chose to use a class, doing something more like this:
1 2 3 4 5 6 7 |
|
That __call__
method allows us to call partial
objects.
So the partial
class makes a callable object.
Adding a __call__
method to any class will make instances of that class callable.
In fact, checking for a __call__
method is one way to ask the question “is this object callable?”
All functions, classes, and callable objects have a __call__
method:
1 2 3 4 5 6 |
|
Though a better way to check for callability than looking for a __call__
is to use the built-in callable
function:
1 2 3 4 5 6 |
|
In Python, classes, functions, and instances of classes can all be used as “callables”.
The distinction between functions and classes often doesn’t matter
The Python documentation has a page called Built-in Functions. But this Built-in Functions page isn’t actually for built-in functions: it’s for built-in callables.
Of the 69 “built-in functions” listed in the Python Built-In Functions page, only 42 are actually implemented as functions: 26 are classes and 1 (help
) is an instance of a callable class.
Of the 26 classes among those built-in “functions”, four were actually functions in Python 2 (the now-lazy map
, filter
, range
, and zip
) but have since become classes.
The Python built-ins and the standard library are both full of maybe-functions-maybe-classes.
operator.itemgetter
The operator
module has lots of callables:
1 2 3 4 5 6 7 |
|
Some of these callables (like itemgetter are callable classes) while others (like getitem
) are functions:
1 2 3 4 5 6 |
|
The itemgetter
class could have been implemented as “a function that returns a function”.
Instead it’s a class which implements a __call__
method, so its class instances are callable.
Iterators
Generator functions are functions which return iterators when called (generators are iterators):
1 2 3 4 5 |
|
And iterator classes are classes which return iterators when called:
1 2 3 4 5 6 7 8 9 10 |
|
Iterators can be defined using functions or using classes: whichever you choose is an implementation detail.
The sorted “key function”
The built-in sorted function has an optional key
argument, which is called to get “comparison keys” for sorting (min
and max
have a similar key
argument).
This key
argument can be a function:
1 2 3 4 5 |
|
But it can also be a class:
1 2 3 |
|
The Python documentation says “key specifies a function of one argument…”. That’s not technically correct because key can be any callable, not just a function. But we often use the words “function” and “callable” interchangeably in Python, and that’s okay.
The defaultdict “factory function”
The defaultdict class in the collections
module accepts a “factory” callable, which is used to generate default values for missing dictionary items.
Usually we use a class as a defaultdict
factory:
1 2 3 4 5 6 7 8 |
|
But defaultdict
can also accept a function (or any other callable):
1 2 3 4 5 6 7 8 9 10 11 12 |
|
Pretty much anywhere a “callable” is accepted in Python, a function, a class, or some other callable object will work just fine.
Think in terms of “callables” not “classes” or “functions”
In the Python Morsels exercises I send out every week, I often ask learners to make a “callable”. Often I’ll say something like “this week I’d like you to make a callable which returns an iterator…”.
I say “callable” because I want an iterator back, but I really don’t care whether the callable created is a generator function, an iterator class, or a function that returns a generator expression. All of these things are callables which return the right type that I’m testing for (an iterator). It’s up to you, the implementor of this callable, to determine how you’d like to define it.
We practice duck typing in Python: if it looks like a duck and quacks like a duck, it’s a duck. Because of duck typing we tend to use general terms to describe specific things: lists are sequences, iterators are generators, dictionaries are mappings, and functions are callables.
If something looks like a callable and quacks (or rather, calls) like a callable, it’s a callable. Likewise, if something looks like a function and quacks (calls) like a function, we can call it a function… even if it’s actually implemented using a class or a callable object!
Callables accept arguments and return something useful to the caller. When we call classes we get instances of that class back. When we call functions we get the return value of that function back. The distinction between a class and a function is rarely important from the perspective of the caller.
When talking about passing functions or class objects around, try to think in terms of callables. What happens when you call something is often more important than what that thing actually is.
More importantly though, if someone mislabels a function as a class or a class as a function, don’t correct them unless the distinction is actually relevant. A function is a callable and a class is a callable: the distinction between these two can often be disregarded.
Want some practice with callables?
You don’t learn by putting more information into your head. You learn through recall, that is trying to retrieve information for your head.
If you’d like to get some practice with the __call__
method, if you’d like to make your own iterable/iterator-returning callables, or if you just want to practice working with “callables”, I have a Python Morsels exercise for you.
Python Morsels is a weekly Python skill-building service. I send one exercise every week and the first 3 are free.
If you sign up for Python Morsels using the below form, I’ll send you one callable-related exercise of your choosing (choose using the selection below).