提问人:Yakov Galka 提问时间:5/30/2023 更新时间:5/31/2023 访问量:60
如何使用 weakref/gc 支持实习对象?
How to intern objects with weakref/gc support?
问:
我正在尝试在 python 中实现非字符串对象的实习。对于字符串,我们有函数。但是,它不支持其他不可变对象。为了不碍事,我知道修改被拘禁对象时可能出现的问题。sys.intern
一个经常被引用的非字符串实习方式是:
S = {}
x = S.setdefault(x, x)
然而,这样的对被拘禁的对象有很强的引用,因此会无限增长,这是我的应用程序中的一个问题。dict
我发现有一种类型可以自动收集未引用的元素。但是,似乎没有一种快速的方法可以在集合中获取持有的对象:WeakSet
S = WeakSet()
S.add(x) # returns nothing
# a very slow way to work around it:
for y in S:
if y == x:
x = y
还有 和 ,但似乎没有 .WeakKeyDictionary
WeakValueDictionary
WeakKeyValueDictionary
那么如何在python中实现这一点呢?
答:
1赞
blhsing
5/31/2023
#1
您可以通过创建对对象的弱引用作为键,然后将对象存储为默认值来模拟:WeakKeyValueDictionary
WeakValueDictionary
from weakref import ref, WeakValueDictionary
def intern(obj, weak_refs=WeakValueDictionary()):
return weak_refs.setdefault(ref(obj), obj)
因此:
import gc
a = frozenset(['x'*10000])
b = frozenset(['x'*10000])
assert a is not b
a = intern(a)
b = intern(b)
assert a is b
print(len(intern.__defaults__[0]))
del a
del b
gc.collect()
print(len(intern.__defaults__[0]))
传递断言和输出:
1
0
演示:https://replit.com/@blhsing/UsableSpecificProcessors
评论
0赞
user2357112
5/31/2023
嗯。。。是的,在这种情况下,当假设的 WeakKeyValueDictionary 的键和值是同一个对象时,只需自己在一侧创建 weakrefs 就可以了。当键和值是不同的对象时,它不会 - 你会遇到清理未正确进行的问题,或者清理未与内部迭代防护正确交互。
0赞
user2357112
5/31/2023
只使用普通函数而不是带有重写的类会更简单。这并不是说你想要一个实际的实例。__new__
Intern
0赞
blhsing
5/31/2023
我把它做了一个类,这样我就可以更容易地输出弱容器的内容,但是是的,如果我把它做成一个函数,把弱容器作为一个参数的默认值,我仍然可以使用这个属性来访问弱容器,只是以一种稍微丑一点的方式,但没关系,因为丑只在调试代码中, 而实际代码在作为函数编写时确实更干净。__defaults__
0赞
blhsing
5/31/2023
键和值始终同步到此应用程序的相同对象,因此不会出现任何清理问题。
0赞
Yakov Galka
6/1/2023
有什么理由让 WeakValueDictionary 带有 ref() 键,而 WeakKeyDictionary 带有 ref() 值?
评论