Почему Слабый прокси не всегда сохраняет эквивалентность в Python? - PullRequest
1 голос
/ 26 августа 2009

MySQLDb использует слабый прокси для предотвращения циклических зависимостей между курсорами и соединениями.

Но вы могли бы ожидать от документации по слабому способу, что вы все еще можете проверить на эквивалентность. Тем не менее:

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 ]

3 голосов
/ 26 августа 2009

Я давно находил дизайн и реализацию 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

Необходимость «вызова» ссылки для получения объекта (или None, если объект с тех пор исчез), к сожалению, делает его непрозрачным (поэтому модуль API БД не мог этого сделать, оставаясь совместимым с API). Я не понимаю, почему MySqlDb вообще хочет слабую ссылку на курсор -> соединение, но если они это делают, я понимаю, почему они чувствовали, что им нужно использовать прокси, а не ссылки. Однако за эту прозрачность платят очень высокую цену!

Кстати, «явный __eq__» трюк (или эквивалентный с __cmp__, в зависимости от типа базового объекта) может вам помочь, даже если он определенно не элегантен!

1 голос
/ 26 августа 2009

Оберните не-прокси с помощью weakref.proxy и используйте оператор идентификации:

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

Двойной вызов weakref.proxy () вернет один и тот же прокси-объект.

0 голосов
/ 26 августа 2009

Если объект является стандартным слабым звеном, вам нужно вызвать его, чтобы получить сам объект.

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

Использование слабых ссылок здесь представляется неправильным: если я создаю соединение, создаю из него курсор и отбрасываю объект соединения, курсор должен оставаться действительным. Не должно быть циклической зависимости, если соединение не хранит список всех курсоров, в этом случае , что - это то, что должно быть слабее.

...