Types and Classes
In the previous lesson, I gave an overview of the course. In this lesson, I’ll be covering the
type() function, the
type type, and classes.
Everything in Python is an object. It’s deja vu all over again. Thanks, Yogi. Each of the objects has a type. The type indicates its nature. A number has the type
int, text has the type
str, and an instance of a person object has the type
type() function tells you what type an object is. Let’s go play with it in the REPL. Let me start out by writing a list.
type() function on it returns the fact that it is an object instance of the
list class. Here’s one of the cats … and the type of that is
str. Interestingly, it’s turtles all the way down. Here’s the third letter of
"tiger", whose type is also a string.
01:09 That’s a bit different from other programming languages that make a distinction between a character and a string. Strings and their substrings are both strings in Python, right down to single-letter instances. How about when you write your own class?
I’ve kept it simple here, creating an empty class. Here’s an instance … and hopefully that’s not a surprise that the type of the instance is the
Dog class. The
__main__ prefix on this is because I’m in the REPL.
If the class were declared in a module, you’d get the module name as the prefix instead. Let’s try something else. That’s the
max() function from the built-in library and that’s
max’s type. Handy that Python distinguishes built-in types from others, huh?
Let me create a class inheriting from
and get an instance. Goodfeathers shout out for the win. There’s the instance and its type. That shouldn’t be too surprising, as that’s how it was built. Do note that it isn’t calling it a class but an
enum. We’ll come back to that later.
Let’s go a little meta. The type of the instance is
Birds, but what is the type of
Birds? Well, it’s a class called
Enum itself, which sort of makes sense, as
Birds inherits from
Enum. There’s a transitive thing going on here. Let’s go grab
and look at it. Now that’s a little weird, isn’t it? The type of
Dog? Yep, the same thing. Same thing actually goes for built-ins.
Type of a
list, type of a
float, they’re all
type type is the top level of the class hierarchy. In fact, you can think of the
type() function the same way you think of the
str() function. When you call
str() on something, it returns its
When you call
type() on something, it returns its
type equivalent. It bears repeating,
type is the top of the hierarchy. Let me show you. Yeah, the type of
type, which you get by calling
03:56 Does that clear it up for you? This is the first of the brain-melting bits on the way to metaclasses. Let’s go talk about classes, and hopefully it’ll become a little clearer.
Python has had classes and objects from almost the beginning, but how they were built changed in Python 2.2. In this version, they added the idea of a base
object that everything can inherit from. Up until Python 3, both the old style and new style of classes was supported.
If you’ve done some object-oriented coding in Python 2 and had your class declaration inherit from
object, this is why Python 3 got rid of the old style.
You can still use the new style declaration inheriting from
object, but if you don’t, Python uses the new style anyways. This saves some typing, but it can cause some confusion for folks who are going back and forth between Python 2 and 3. Hopefully, that’s fewer and fewer of you nowadays.
04:55 Let me demonstrate these different class declarations in the REPL. I’m in a 2.7 REPL. Let me just prove that.
2.7.18. Now let me declare a class using the original syntax.
If you’ve used Python 2’s new style, note that I have not inherited from
object here. This can actually be a source of a tricky bug in Python 2.
05:27 If you mean to use the new style and forget the object inheritance, your classes may not behave the way you expect. Anyway, let’s play with the old style for a bit.
apple instance. And the
.__class__ attribute of an object indicates what class it’s from. Here it’s showing that
Fruit declared in
__main__. Again, being in the REPL is what causes
__main__ to be the module name.
instance. That’s an old-style thing. Running
type() on the class itself gives
classobj. Again, an old-style thing.
06:09 All right, out with the old, let’s talk about the new. In this case, new is kind of relative. It was introduced in Python 2.2, which was released December 21, 2001.
06:23 I suspect some of you may have been born after this new thing. Anyhow, the relativity of new notwithstanding, let’s use it.
The new-style class declaration inherits from
object. You can actually come at this the other way around. Inheriting from
object is what distinguishes this as a new-style class.
06:46 Without object, you get the old-style class. Offer limited to Python 2, offer may not be valid in some states, buyer beware, caveat emptor, et cetera, et cetera.
carrot is an instantiation of
__main__.Vegetable. The only obvious difference between the string representation of the old and new class is the old class includes an object ID reference, and the new one does not.
The type, on the other hand, is quite different. This is the kind of result you saw when I was playing with the
type() function before. The type of a new class object is the object’s class, where the old-style object’s type was
And like you saw before, the type of a new-style class is
type. Back to my type of
type found with the
type() function. Okay, that’s Python 2. How about Python 3?
3.11.2. New REPL, new class.
Let me instantiate some dessert. Sundae, yummy sundae. I apologize, Bono. And the type of
sundae is the
Dessert class. This shouldn’t be a surprise.
You’ve seen this already. The point I’m trying to make is in Python 3, you no longer need to inherit from
object. Python 3 uses the same syntex as Python 2’s old-style classes, but actually produces new—that’d be 2001-new—style classes.
This was done because the old style isn’t supported anymore, and there’s no need to make Python 3 programmers type out the extra inheritance. Since
Dessert is a class, its type is
08:53 For compatibility’s sake, you can still do it the old new way.
Love me some gnocchi. Type of the instance is the class, and the type of the class is
type. Essentially, although not necessary, you can inherit from
object in Python 3 and get the same result as not doing it.
09:23 This makes compatibility easier when you’re writing scripts that need to work in both, say 2.7 and a 3 variant. Let’s get graphical and visualize the new style.
Starting with my
sundae instance, which was created by the
Dessert class, and the type of
Dessert is type, and the type of
Does the picture help? Saying the type of
type is fun. All right, I’ll stop now. The
type() function can be used as a class factory as well. In the next lesson, I’ll show you just that.
Become a Member to join the conversation.