From the Python 3.9 documentation :
If a name binding operation occurs anywhere within a code block, all uses of the name within the block are treated as references to the current block.
The line x = 99 in the class definition, makes x local to the class block.
In a class block,
References follow the normal rules for name resolution with an exception that unbound local variables are looked up in the global namespace.
At the point the print(x,y) is executed, x is an unbound local variable. It's value is looked up in the global namespace, where x = 0.
When a name is used in a code block, it is resolved using the nearest enclosing scope.
When print(x, y) is executed, the value of y is looked up in the nearest enclosing scope, which is the body of def f(), where y = 1.
So print(x, y) outputs 0 1.