Why shouldn't I just use python code for configuration?

This isn’t uncommon and can often seem like a nice, simple solution although using a turing complete language for configuration will often have nasty side effects.

Why does using YAML (or indeed, any configuration language) avoid this? Because they are less powerful languages than python.

While this may not intrinsically seem like a good thing (more power seems better at first glance), it isn’t:

A good way of refactoring, in fact, is to take a large chunk of turing complete python code that can be transformed directly into YAML with no loss in expressiveness and and to transform it - for example, a list of translation strings, countries or other configuration information.

This has a number of advantages.

Less powerful languages are easier to maintain and can be given to non-programmers to maintain.

For example, a YAML translations configuration file like this could easily be edited by a non programmer:

Hello:
  French: Bonjour
  German: Guten tag
Goodbye:
  French: Au revoir
  German: Auf wiedersehen

Whereas this python is more likely to cause problems, especially in a large file:

TRANS = {
    "Hello": {
        "French": "Bonjour",
        "German": "Guten tag",
    },
    "Hello": {
        "French": "Bonjour",
        "German": "Auf wiedersehen",
    },
}

It also makes it easier to have the markup generated by another program or a templating language. While you technicall can do this with turing complete code, it will often lead to a debugging nightmare - just ask C++ programmers!