With nested scopes, the variable lookups are easy. They occur in a chain starting with locals, through enclosing defs, to module globals, and then builtins. The rule is the first match found wins. Accordingly, you don’t need a “global” declaration for lookups.
In contrast, with writes you need to specify which scope to write to. There is otherwise no way to determine whether “x = 10” in function would mean “write to a local namespace” or “write to a global namespace.”
Executive summary, with write you have a choice of namespace, but with lookups the first-found rule suffices. Hope this helps 🙂
Edit: Yes, it is this way “because the BDFL said so”, but it isn’t unusual in other languages without type declarations to have a first-found rule for lookups and to only require a modifier for nonlocal writes. When you think about it, those two rules lead to very clean code since the scope modifiers are only needed in the least common case (nonlocal writes).