当他们指出一种方法时,为什么我的弱点在水中死了?

时间:2011-03-22 16:44:22

标签: python weak-references observer-pattern

  

可能重复:
  Why doesn't the weakref work on this bound method?

我在观察者模式中使用了弱点,并注意到一个有趣的现象。如果我创建一个对象并添加其中一个方法作为Observable的观察者,那么引用几乎立即就会消失。谁能解释一下发生了什么?

我也很想知道为什么这可能是一个坏主意。我已决定不使用weakrefs,只需确保使用Observable.removeobserver正确清理后,但我的好奇心在这里杀了我。

以下是代码:

from weakref import ref
class Observable:
    __observers = None
    def addobserver(self, observer):
        if not self.__observers:
            self.__observers = []
        self.__observers.append(ref(observer))
        print 'ADDING observer', ref(observer)

    def removeobserver(self, observer):
        self.__observers.remove(ref(observer))

    def notify(self, event):
        for o in self.__observers:
            if o() is None:
                print 'observer was deleted (removing)', o
                self.__observers.remove(o)
            else:
                o()(event)

class C(Observable):
    def set(self, val):
        self.notify(val)

class bar(object):
    def __init__(self):
        self.c = C()
        self.c.addobserver(self.foo)
        print self.c._Observable__observers

    def foo(self, x):
        print 'callback', x  #never reached

b = bar()
b.c.set(3)

这是输出:

ADDING observer <weakref at 0xaf1570; to 'instancemethod' at 0xa106c0 (foo)>
[<weakref at 0xaf1570; dead>]
observer was deleted (removing) <weakref at 0xaf1570; dead>

主要注意的是调用addobserver后的print语句显示weakref已经死了。

2 个答案:

答案 0 :(得分:3)

每当你引用一个对象方法时,就会发生一些魔法,这就是那种阻碍你的魔法。

具体来说,Python在对象的类上查找方法,然后将其与对象本身组合以创建一种称为绑定方法的可调用方法。每次例如计算表达式self.foo,创建一个新的绑定方法实例。如果你立即对它进行弱化,那么就没有对绑定方法的其他引用(即使对象和类的方法都有实时引用)并且weakref会死掉。

请参阅this snippet on ActiveState了解解决方法。

答案 1 :(得分:1)

每次访问实例的方法obj.m时,都会生成一个包装器(称为“绑定方法”),它可以调用并添加selfobj)作为第一个参数。调用。这是一个简洁的传递self“隐式”的解决方案,并允许首先传递实例方法。但这也意味着每次键入obj.m时,都会创建一个新的(非常轻量级)对象,除非你对它进行(非弱)引用,否则它将被GC,因为没有人会为你保持活力。