Machine code is arguably unreadable; where instructions are encoded as numbers: as fields of numbers; numbers for offsets, numbers for constants, numbers for opcodes, numbers for registers. There are no code labels, no data labels — just numbers.
Assembly language introduces mnemonics, register names, and (yay!) labels — and this source code is readable as text. Though more readable, and importantly more easily edited, none-the-less, lines of assembly mostly correspond directly to machine code instructions.
"High-level" computer languages are also human readable text, though have at least 2 features that differentiate from assembly language. First, the notion of structured statements. And, second, variations on types & declarations.
Structured statements (if-then, if-then-else, while, for, do-while, functions) allow logical nesting of control structures without using labels — a huge improvement over assembly language.
Types help prevent illegal program states, often at compile time — a program that tries to multiply a string gets a compile-time error — not being allowed to run at all.
In a high level language program we can declare a variable with a type, and that type for that variable is honored for the duration of the program. A machine code (or assembly) program also knows about types, but much less by declarations, instead rather by repetition in the instruction stream — each time a variable is accessed a type-appropriate instruction variation should be used (sign, data size, etc..).