Strings not referenced by dicts?
Look at this Python code:
from gc import get_referrers as refs
x = 'x'
d = {x:x}
print(d in refs(x))
It prints False. That's weird by itself, but becomes much weirder when you consider the following:
If x is a number (int, float, complex, Fraction, Decimal) instead of a string, it still prints False. For bytes and bytearray, too. But for every other type (hashable if used as key, like tuple or frozenset - but many other, if used as value only), it prints True.
If d is any other container (set, list, tuple...) containing x, it prints True. Only for a dict, it prints False. Also, it doesn't matter if x is a key or a value, or as above, both.
I thought in Python every object is a reference (as opposed to Java, which has primitive types, or Ruby, which value-types small ints), but now it seems str and int are kinda primitive types, that aren't referenced. But on the other hand, why only in dicts??
I also know that ints from -5 to 256 are cached in CPython (and small strings can be interned), so it makes sense not to refcount them, since they will never be deleted anyway, but this works for any integers (and long strings) I've tried, much larger than that range.
Does anybody know what's going on here?
--- UPDATE ---
Curiouser and curiouser... it seems datetime.{datetime, date, time} classes have the same "unreferenced" behaviour. Now, I know one thing that those, AnyStr and Number have in common: their hashes are randomized with a per-session salt. But this doesn't make any sense, since the behaviour is observed even when these are merely values in dicts, not keys. And values are not hashed. Or are they?
From gcmodule.c
:
Certain types of container cannot participate in a reference cycle, and so do not need to be tracked by the garbage collector. Untracking these objects reduces the cost of garbage collections. However, determining which objects may be untracked is not free, and the costs must be weighed against the benefits for garbage collection.
...
Dictionaries containing only immutable objects also do not need to be tracked. Dictionaries are untracked when created. If a tracked item is inserted into a dictionary (either as a key or value), the dictionary becomes tracked. During a full garbage collection (all generations), the collector will untrack any dictionaries whose contents are not tracked.
Basically, since object in Python are reference-counting, the goal of garbage collector is to break reference cycles, other unreferenced objects are destroyed when last reference goes away. For optimization, garbage collector doesn't keep track of certain objects which simply can never participate in reference cycles.
So, strings are referenced. However, the garbage collector is not interested in these dictionaries at all and therefore gc.get_referrers()
doesn't list them.
上一篇: AppBar在滚动时隐藏视图直到折叠
下一篇: 没有被字典引用的字符串?