为什么weakproxy并不总是保留python中的等价?

时间:2009-08-26 00:47:18

标签: python weak-references

MySQLDb使用弱代理来防止游标和连接之间的循环依赖。

但是你会期望从weakref的文档中你仍然可以测试等价。然而:

In [36]: interactive.cursor.connection.thread_id()
Out[36]: 4267758

In [37]: interactive.web_logic.conns.primary.thread_id()
Out[37]: 4267758

In [38]: interactive.cursor.connection == interactive.web_logic.conns.primary
Out[38]: False

In [39]: interactive.cursor.connection
Out[39]: <weakproxy at 0x3881c60 to Connection at 0x94c010>

In [40]: interactive.web_logic.conns.primary
Out[40]: <_mysql.connection open to 'xendb01' at 94c010>

如何判断连接是否相同?

3 个答案:

答案 0 :(得分:3)

我早就发现weakref.proxy的设计和实现有些不稳定。证人...

>>> import weakref
>>> ob=set(range(23))
>>> rob=weakref.proxy(ob)
>>> rob==ob
False
>>> rob.__eq__(ob)
True

......绝对特别!在实践中,我在weakref中使用的是弱键或有时弱值词典;但是weakref.ref比代理包装器更健全:

>>> wr=weakref.ref(ob)
>>> wr()==ob
True

需要“调用”ref来获取对象(或者如果对象已经消失,则为None),但遗憾的是它使得它不透明(因此DB API模块在保持与API兼容的情况下无法执行此操作)。我不明白为什么MySqlDb想要弱光标 - >连接引用,但如果他们这样做,我明白为什么他们认为他们必须使用代理而不是refs。然而,人们为这种透明度付出了非常高的代价!

顺便说一下,“显式__eq__”技巧(或等同于__cmp__的技巧,取决于基础对象的类型)可能对你有帮助,即使它绝对不优雅!

答案 1 :(得分:1)

使用weakref.proxy包装非代理并使用identity运算符:

>>> interactive.cursor.connection is weakref.proxy(interactive.web_logic.conns.primary)
True

两次调用weakref.proxy()将返回相同的代理对象。

答案 2 :(得分:0)

如果对象是标准的弱参照,则需要调用它来获取对象本身。

import weakref
class Test(object): pass
a = Test()
b = weakref.ref(a)
a is b() # True
a == b() # True

在这里使用weakrefs似乎是错误的:如果我构造一个连接,从中创建一个游标,并丢弃连接对象,则游标应该保持有效。除非连接保留所有游标的列表,否则不应存在循环依赖关系,在这种情况下, 应该是弱参数。