For a literal that represents a mutable object, every evaluation of the literal must generate a new object.
For a literal that represents an immutable object, whether a new object is created comes down to arbitrary implementation details. It could have chosen to use the same tuple. It could use the same tuple in a future release, or in a different Python implementation. Your example actually does reuse tuples if you call
main repeatedly, but different tuples for
c. You shouldn't rely on it being one way or another.
If you want to see the particular implementation details for this case, the CPython bytecode compiler ordinarily merges equivalent constants together in a code object (the mechanism involves a dict, with some extra work to keep things like
1 from merging), but the peephole optimization pass that precomputes the 3 tuples occurs in a postprocessing phase that doesn't have the deduplication machinery in place.