In C++ there are just objects and classes, where objects are instances of classes.
In Python, a class definition (i.e., the body of a class) is called an object. And
In a very real sense, everything in Python is an object: a class (or any type) is an object, a function is an object, a number is an object... And every object has a type. A "type" is a particular type of object (a class, if you wish), with additional data describing the various attributes of the type (functions, etc.). If you're used to C++, you can think of it as something like:
struct Type;
struct Object // The base class of everything.
{
Type* myType;
// Some additional stuff, support for reference counting, etc.
};
struct Type : Object
{
// Lots of additional stuff defining type attributes...
};
When you define a new class in Python, you're really just creating a new
instance of Type; when you instantiate that class, Python initializes
the myType member with a pointer to the correct instance of Type.
Note, however, that everything is dynamic. When you define a type
Toto (by executing a class definition—even defining a type is a
runtime thing, not compile time, as in C++), the Python interpreter
creates an instance of Type, and puts it in a dictionary
(map, in C++ parlance) somewhere. When the interpreter
encounters a statement like:
x = Toto()
, it looks up Toto in the dictionary: if the Object referred to has
the type Type, it constructs a new instance of that object, if it has
type Function (functions are also objects), it calls the function.
(More generally, a type/class may be callable or not; if the type of the
Object found in the dictionary under Toto is callable, the Python
interpreter does whatever the object has defined "call" to mean. Sort
of like overloading operator()() in C++. The overload of
operator()() for Type is to construct a new object of that type.)
And yes, if you come from a classical background—strictly procedural, structured, fully-compiled languages, it can be pretty confusing at first.