The allocation unit cannot be smaller that 1 byte. For a 1-bit variable (a Boolean value) you have to allocate at least 8 bits, 7 of them unused.
A modern CPU operates on 64 bits (8 bytes), some on 32 bits = 4 bytes; 16-bit embedded controllers are common, 8-bit controllers are already rare. RAM also works more efficiently with larger widths, and normally expects alignment on 4-byte border for efficient fetches. This is why a 1-bit value can even take up 4 bytes in memory.
A Python integer is an object. Yes, you can invoke methods right on an integer constant:
(100).bit_length(). This means that the actual integer value is stored along with a lot of other information.
Python integers try to adapt to the size of data, more so in Python 3 were an integer of any length is an object of the same type, just allocating enough bytes to store the value.
You can indeed pack values of small magnitude to more efficiently use the bits available. This is common is storage formats, especially where bandwidth is important. E.g. a GPU can work with textures packed in various ways, both as integers and (short) floats. Most modern CPUs have "vector instructions" to work with several independent 16-bit and 8-bit integers packed into 32- or 64-bit registers.