使用弱引用来实现组合

时间:2013-07-28 18:28:05

标签: python composition

弱引用可用于传递复合对象属性?假设您有一个具有属性A的类。您的代码的任何部分现在都可以获取对A的引用,但是如果删除了由A组成的类实例,则必须删除它,但如果在其他地方引用它则不会。使用弱引用实现这种行为是可以的,因为对A的唯一强引用是由组合对象拥有的吗?

class B:
 def __init__(self):
   self.A = SomeClass()

3 个答案:

答案 0 :(得分:1)

弱引用用于避免保留实例,而不是确保在反对者被删除时删除对象。

SomeClass()实例只有 才能从内存中删除所有对它的引用被删除(任何不是弱引用的引用都是反而强烈的参考。)

如果B().A属性是SomeClass()实例的引用,那么当B().A引用反弹到某个内容时,该实例将被删除else或已清除(如果B()被删除,B().A属性将被自动清除),因为SomeClass()的引用计数降至0。

换句话说,如果B().A是对SomeClass()的弱引用,并且没有SomeClass()的其他引用,则取消引用{{1}将返回B().A,因为None已被删除。

然而,使用SomeClass() 之外的弱引用可能是确保B().A成为唯一强引用的方法B().A实例。

答案 1 :(得分:0)

Python删除标记潜在删除的对象并递减引用计数器 - 最终删除仅在引用计数器达到零时发生。

答案 2 :(得分:0)

如果我理解正确,你的用例是这样的:

b = B()

def reset_b():
    global b
    b = B() # drops the reference to b, so it (and b.A) should be garbage collected

def get_a():
    return b.A

您担心的是,A返回的已保存get_a引用在b重置后仍然有效。如果这是正确的,那么弱引用可能是一种解决方法:

import weakref

def get_a():
    return weakref.proxy(b.A)

如果proxy对象在其所引用的b.A对象被删除后使用,则get_a对象将引发大多数操作的异常。

我不确定这是一个好的设计。一个更好的解决方案可能只是简单地记录{{1}}的结果不应该长期缓存。相反,只要需要新的引用,就应该再次调用它。这不需要任何复杂的引用方案或异常处理,并且更容易思考和测试。