Because allowing arbitrary attributes would create an insane amount of memory bloat
The reason object instances don't have a __dict__ is that, if any class in a class hierarchy has a __dict__, then all instances of the subclasses have it (otherwise, the subclasses wouldn't be compatible with the parent classes; the initializer for the parent almost certainly tries to set attributes that need __dict__ after all), even if they intended to opt-out.
object is the parent class for all classes in Python, so if it had a __dict__ to hold arbitrary attributes, every class in Python would have it. And that would make literally every instance of every object in Python consume another 4-8 bytes just for the pointer, even if Python didn't create an actual dict there until someone tried to auto-vivify an attribute. On a 64 bit build, that would mean every int increases its memory consumption from 28 (higher for large numbers) bytes to 36. Every float from 24 to 32. And confusingly, every dict would have to provide __dict__.
Worse, for performance/memory consumption on the CPython reference interpreter, is that if every object can contain __dict__, then every object can potentially form part of a reference cycle. The cyclic garbage collection can normally ignore "leaf" objects (any object that can't contain another arbitrary object), so it doesn't track ints, floats, str, bytes, etc. If everything has a __dict__, then everything can be part of a reference cycle. And that means it secretly allocates two more pointers (8-16 more bytes per instance) to put it in a linked list with all the other objects for the garbage collector to track, and that means the cyclic collector has to traverse it each time its generation is collected, slowing collection. Between those two changes alone, if object provided __dict__ literally every float object in the program would double in size. Smallish ints would nearly double. Python isn't a super-memory efficient language, but adding >50% overhead for common objects just on the chance someone might want to attach arbitrary attributes to them (a ridiculously rare need) is a terrible idea.
And that's before we even get into the problem of hashability; Python hashable built-ins are immutable. If everything has a __dict__, then nothing is truly immutable, and either the hashing and equality functions have to ignore those arbitrary attributes (possible, but potentially confusing), or you have to hope users never modify an object inserted into a set or used as a dict key (because it could retroactively invalidate objects used for that purpose).
When you want to have a cheap object that can accept arbitrary attribute
object() doesn't provide __dict__ to avoid this issue. If you want a simple namespace to assign attributes to without defining your own class, types.SimpleNamespace provides this functionality (along with providing a useful repr that object wouldn't provide).