Locked learning resources

Join us and get access to thousands of tutorials and a community of expert Pythonistas.

Unlock This Lesson

Locked learning resources

This lesson is for members only. Join us and get access to thousands of tutorials and a community of expert Pythonistas.

Unlock This Lesson

Calling Non-Functions

00:00 In the previous lesson, I dove deeper into strings. This lesson is a bit of a tangent explaining why I’ve been saying “string callable” instead of “string function”. Say it with me: Everything in Python is an object,

00:15 which means everything is an instance of a class. In fact, functions themselves are objects, but the reverse isn’t true. Not everything that looks like a function is one.

00:27 The convention you’re supposed to follow in your own code is classes get CamelCase, that’s capitalization, whereas variables, functions and methods get snake_case that’s lowercase with underscores.

00:39 Turns out, though, many of the built-ins that are named as if they’re functions and called as if they’re functions using lowercase snake case are actually classes.

00:50 Classes can be callable. Hence why I’ve been saying callable all this time when talking about the string callable. I’ve been pedantically correct throughout this course to make a point not to be pedantic about it.

01:04 If someone called it a string function, I wouldn’t correct them. But learning the difference between a function and a callable exposes more of the inner workings of Python, which I’m going to delve into just a tiny bit here.

01:16 This callable thing goes for all type conversions in Python, and as everything in Python is an object,

01:24 hmm must have worn it out. When you convert from one thing to another, you are getting a new instance of the new thing. And new instances of objects are done by using parentheses on a class, hence, calling it.

01:39 Let’s head into the REPL to see this pedantic difference in practice.

01:44 Let’s start by converting a number to a string using our old faithful friend, the string callable.

01:51 And now I’ll evaluate it, and I liked that so much I’m going to do it again, ditto. Now the contents of these two objects are the same,

02:04 x == y, but to be perfectly clear, they’re not the same object. The is comparator checks if references point to the same object in memory.

02:16 I was a little tricky here. Python does some optimization things, so pointing two variables at the same string might actually result in the same object. But by explicitly using the string callable, I’m explicitly constructing two object instances.

02:31 Python doesn’t care that I’ve initialized them both with the same content. They are two different objects. Whenever you use the string callable, you are creating a new string object, instantiating it with the return result of __str__() called on the object passed in as an argument.

02:49 One way to see the difference is by using the built-in id() function, which actually is a function. It returns a number indicating the memory location of an object.

02:59 This is an internal CPython thing and you can’t really do anything with the value, but by examining it, you can see if two variables point to the same place.

03:09 Let me show you this. Calling id() on x,

03:13 don’t worry what the number is, just compare it to the number from y, and they’re different. And in fact, if you’re running this code on your own, the two different values will be different for you as well.

03:25 There are two different bits of memory because there are two objects. That’s because the string callable is a callable and not a function. It constructs a new object, even if it has a lowercase name to try and fake you out.

03:40 This is all connected to the fact that strings are classes. If you use the type() callable, which is a callable and not a function, even though it looks like a function, it tells you what type an object is.

03:51 So the type of x is a string. The type of the string callable is a type and confusingly the type type is what Python calls classes.

04:05 Why, is for another day, just notice the difference.

04:09 This isn’t unique to the string callable. In fact, it works for any callable you use to do type conversion.

04:16 And just so you don’t think that everything must look that way, let’s compare it to say eval(),

04:23 which actually is a function. And so its return type tells you not only that it’s a function, but that it’s a built-in one.

04:32 In the next lesson, I’ll show you how to override the __str__() and __repr__() methods in your own classes.

Avatar image for Jordan Bell

Jordan Bell on March 10, 2025

From a mathematical point of view, it feels like a factory function is a genuine function.

If P() is a class factory function, it’s a function from the empty set to the set of instances of the class.

If the factory function has parameters, we don’t even have to deal with the oddness of thinking about functions from the empty set to something else.

It’s not quite clear to me what distinction there is between function and callable.

Avatar image for Bartosz Zaczyński

Bartosz Zaczyński RP Team on March 11, 2025

@Jordan Bell A Python callable is a broader term encompassing several more specific types, like:

Although they all support the parentheses operator, with which you can call them, these callable types differ in subtle ways on a low level. For example, all classes are implicitly callable to let you invoke their constructor. A lambda function must contain precisely one expression, and it can’t have any statements. Objects can carry an additional state, while functions typically don’t.

Python’s official documentation defines str() both as a built-in function and as a standalone data type:

So, you’re right in your thinking. The difference between a function and a callable isn’t as important from a practical point of view, but the details lie in the implementation.

When in doubt, you can always use the built-in callable() function to test whether an object is callable or not:

>>> callable(str)
True

>>> callable("Hello, World!")
False

This will tell you if you can use the parentheses to call your object.

Avatar image for Jordan Bell

Jordan Bell on March 11, 2025

What I wrote was wrong, so don’t bother with my thoughts about the abstract point of view.

But I am curious about what the essential difference between a function and callable is.

Avatar image for Jordan Bell

Jordan Bell on March 11, 2025

Thank you for the response, Bartosz!

The last part of your reply clears things up nicely:

So, you’re right in your thinking. The difference between a function and a callable isn’t as important from a practical point of view, but the details lie in the implementation.

When in doubt, you can always use the built-in callable() function to test whether an object is callable or not:

Become a Member to join the conversation.