I believe that the reason this code actually works is the way Python deals with mutable object references and they way they are passed into/out of functions... In essence, tx2 and tx3 are actually just references to the original "tx" object (although I'm not a Python expert, so feel free to correct me if I'm wrong!)...
So, when the code is passing "tx2" and "tx3" to the sign() function... we're actually using the original "tx" object. So when the (accidental?) serialisation of "tx" happens at the end, it all works out.