Why does get_template_part() break variables?

A script loaded within a function call will only work within the immediate scope of where require or include was used. So really only variables present when load_template() is called will be accessible to the loaded script (unless you use global $myvar of course).

The reason vars like $post and $wp_query are available to the script is because load_template() globals them in before loading the script.

If you wanted to make sure your script can access certain vars, either global them in or add them to the $wp_query->query_vars array before loading (not recommended but depending on the task it might be the only feasible option), as those get extracted into the local scope before loading the script.