can it be that a set will be internally rehashed or reallocated by Python interpreter during the execution of some code that doesn't modify that set explicitly?
No.
Hashable from python glossary:
An object is hashable if it has a hash value which never changes during its lifetime
Set docs
The elements of a set must be hashable.
Sets will not be rehashed during their lifetime.
Lists preserve the insertion order so the order of a list built from a set is the order given from the set and that will not change since hashes don't change.
As mentioned, hashes are randomized across executions as noted by this Bash one-liner that builds:
- A list based on object's hash.
- A set from that list. Order changes due to hash collisions.
- A list from the set. Same order of the set.
for i in 1 2 3 4; do python3.12 -c 'import string;l=[f"ba{c}" for c in string.ascii_lowercase if hash(f"ba{c}") % 8 == 2 ];print(f"{l}\n{set(l)}\n{list(set(l))}\n")';done
Result
['baa', 'bah', 'bai', 'bam', 'bap']
{'baa', 'bap', 'bah', 'bai', 'bam'}
['baa', 'bap', 'bah', 'bai', 'bam']
['bag', 'bai', 'bal', 'bax']
{'bai', 'bag', 'bal', 'bax'}
['bai', 'bag', 'bal', 'bax']
['bae', 'bai', 'baq', 'bax']
{'baq', 'bae', 'bax', 'bai'}
['baq', 'bae', 'bax', 'bai']
['bae', 'bap', 'bax']
{'bae', 'bap', 'bax'}
['bae', 'bap', 'bax']
But, we can turn off hash randomization by setting PYTHONHASHSEED to a constant value
for i in 1 2 3 4; do PYTHONHASHSEED=1 python3.12 -c 'import string;l=[f"ba{c}" for c in string.ascii_lowercase if hash(f"ba{c}") % 8 == 2 ];print(f"{l}\n{set(l)}\n{list(set(l))}\n")';done
Result
['bac', 'bah', 'bak', 'baw']
{'bac', 'bak', 'bah', 'baw'}
['bac', 'bak', 'bah', 'baw']
['bac', 'bah', 'bak', 'baw']
{'bac', 'bak', 'bah', 'baw'}
['bac', 'bak', 'bah', 'baw']
['bac', 'bah', 'bak', 'baw']
{'bac', 'bak', 'bah', 'baw'}
['bac', 'bak', 'bah', 'baw']
['bac', 'bah', 'bak', 'baw']
{'bac', 'bak', 'bah', 'baw'}
['bac', 'bak', 'bah', 'baw']
iter_result = list(s)