But keep in mind that assigning to a Vision component property causes that property's change event to fire right there, recursively if called from within that event script.
The script is running twice because you're changing the property from within a property change script. The end of the script causes a property change, and then that property change causes it to run again.
The reliable new value in recursion is in event.newValue. Consider adding that to your print at the top of your script. Consider also using single print statements.
For a simpler demonstration, make a temporary component and add a custom integer property Test, then add this change event:
The key insight is that property change events can sometimes happen before the property is "latched". Ideally, this would be consistently either before or after, but between fifteen years of our own component development and the underlying system (Java Swing) I can guarantee that it's not; different properties on different components (or even the same component) will fire before or after the property has actually 'latched' and will reflect the new value when it is next read.
As Phil said - the only safe bet is to rely on event.newValue.
Somewhat confusingly, what's actually happening is when you say print x, y
You're creating a tuple(x, y) and passing that to print. 99% of the time this doesn't matter and it just does what you want, but it's a potentially useful bit of trivia.