微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

Python – 如何调节weakproxy对象的列表

因此,当涉及到检查引用是否为实时,或者“解除引用”它们,或实际上几乎任何方式时,weakref.proxy对象看起来都不像weakref.ref对象那样工作. :P

他们似乎仍然有自己的位置 – 比如维护一个响应事件的对象列表.由于不需要对它们进行deref来调用它们弱引用的对象上的方法(与需要首先调用的weakref.ref对象不同),因此在数千次迭代中使用代理对象可以获得一些时间.然而,它们似乎更难以实际识别为“死”,并且一旦它们引用的对象消失就会立即清理.例子 –

>>> mylist    #note the object at mylist[1] is already dead...
[<weakproxy at 0x10ccfe050 to A at 0x10ccf9f50>,<weakproxy at 0x10ccfe1b0 to nonetype at 0x10cb53538>]
>>> for i in mylist[:]:
...     try:
...             getattr(i,'stuff')   #the second arg Could be any sentinel;
...                                   #I just want to hit a ReferenceError
...     except AttributeError:
...             pass
...     except ReferenceError:
...             mylist.remove(i)
... 
Traceback (most recent call last):
  File "<stdin>",line 7,in <module>
ReferenceError: weakly-referenced object no longer exists

所以它存在于那里,它实际上不能直接引用或像变量一样传递,因为这显然会导致Python“取消引用”它并使用它弱指向的对象. (或者其他的东西.)

到目前为止,我发现的唯一似乎有点可靠的是通过try / except路由它,但感觉有点像一个小跑.

for i,obj in enumerate(mylist):
    try:
        obj.__hash__
    except ReferenceError:
        del mylist[i]

它可以工作,但Python往往是“所有事情的一个正确答案”语言,这感觉就像一个非常大的解决方案 – 我可能错了,但如果列表足够大,不会复制列表以这种方式适应问题?

不幸的是,我似乎真的认为这是一个不涉及类型检查或其他垃圾的潜在解决方案,但我猜我在weakref文档中错过了一些关于如何正确处理weakref.proxy对象的内容.感觉就像’确保weakref.proxy不是特殊情况,因此使用try / except是一次性实用程序.

因此,如果我在使用try / except的假设是正确的,那么有没有更好的方法来识别死的weakref.proxy对象?

编辑:我已经接受了答案,所以谢谢你 – 尝试/除了似乎是唯一可以接受的.

至于为什么我没有使用WeakSets – 允许我发布一个简单的演示,最终导致我使用代理对象.

>>> from weakref import WeakSet,proxy
>>> import cProfile
>>> class A(object):
...     def __init__(self):
...             self.x = 0
...     def foo(self,v=1):
...             self.x += v
... 
>>> Stick = A()
>>> Dave = A()
>>> Jupiter = A()
>>> ##just a list of objects,no fancy
>>> one_group = [Stick,Dave,Jupiter]
>>> cProfile.run("for i in xrange(0,2**16): [x.foo(i) for x in one_group]")
         196610 function calls in 0.136 seconds

   Ordered by: standard name

   ncalls  tottime  percall  cumtime  percall filename:lineno(function)
   196608    0.049    0.000    0.049    0.000 <stdin>:4(foo)
        1    0.087    0.087    0.136    0.136 <string>:1(<module>)
        1    0.000    0.000    0.000    0.000 {method 'disable' of '_lsprof.Profiler' objects}


>>> Stick.x
2147450880
>>> Dave.x
2147450880
>>> Jupiter.x
2147450880

所以我们知道它有效,而且我们知道65k迭代的速度相当快.似乎体面;让我们来看看WeakSets.

>>> ##Now a WeakSet of objects. should be ideal; but...
>>> two_group = WeakSet((Stick,Jupiter))
>>> cProfile.run("for i in xrange(0,2**16): [x.foo(i) for x in two_group]")
         851970 function calls in 0.545 seconds

   Ordered by: standard name

   ncalls  tottime  percall  cumtime  percall filename:lineno(function)
   196608    0.055    0.000    0.055    0.000 <stdin>:4(foo)
        1    0.158    0.158    0.545    0.545 <string>:1(<module>)
    65536    0.026    0.000    0.026    0.000 _weakrefset.py:16(__init__)
    65536    0.043    0.000    0.051    0.000 _weakrefset.py:20(__enter__)
    65536    0.063    0.000    0.095    0.000 _weakrefset.py:26(__exit__)
    65536    0.024    0.000    0.024    0.000 _weakrefset.py:52(_commit_removals)
   262144    0.159    0.000    0.331    0.000 _weakrefset.py:58(__iter__)
    65536    0.009    0.000    0.009    0.000 {method 'add' of 'set' objects}
        1    0.000    0.000    0.000    0.000 {method 'disable' of '_lsprof.Profiler' objects}
    65536    0.008    0.000    0.008    0.000 {method 'remove' of 'set' objects}

过早优化?罗. :)这大约慢4倍.啊呀.

>>> ##Now finally,a list of proxy objects
>>> three_group = [proxy(x) for x in one_group]
>>> cProfile.run("for i in xrange(0,2**16): [x.foo(i) for x in three_group]")
         196610 function calls in 0.139 seconds

   Ordered by: standard name

   ncalls  tottime  percall  cumtime  percall filename:lineno(function)
   196608    0.050    0.000    0.050    0.000 <stdin>:4(foo)
        1    0.089    0.089    0.139    0.139 <string>:1(<module>)
        1    0.000    0.000    0.000    0.000 {method 'disable' of '_lsprof.Profiler' objects}

基于这些数字,我开始认为,维护必须正确注释为已释放的对象列表的最简单,最快的方法是使用代理对象.我认为将try / except作为“清单清除”的策略性使用将确保死代理不会导致错误.
为了方便起见,我可能会回到使用weakref.ref对象的方法,但代理对象的使用对于它们看似“直接”访问对象很有趣.

解决方法

您的弱引用对象在mylist.remove(i)行上再次引发ReferenceError异常,而不是在循环或访问时引发,很可能是因为Python尝试在代理上使用__eq__方法.

您的第二种方法使用索引而不会触发该异常,在第一个循环中使用它:

remove = set()
for index,proxy in enumerate(mylist):
    try:
        getattr(proxy,'stuff')
    except AttributeError:
        pass
    except ReferenceError:
        remove.add(index)

mylist = [p for i,p in enumerate(mylist) if i not in remove]

演示:

>>> import weakref
>>> class Foo(object): pass
... 
>>> remove = set()
>>> mylist = [weakref.proxy(Foo())]  # instant dead proxy
>>> for index,proxy in enumerate(mylist):
...     try:
...         getattr(proxy,'stuff')
...     except AttributeError:
...         pass
...     except ReferenceError:
...         remove.add(index)
... 
>>> remove
set([0])

如果你特别想要一个测试对象仍然存在的函数,你可以使用:

def proxy_live(p)
    try:
        bool(p)
    except ReferenceError:
        return False
    return True

但是考虑到布尔测试本身可以触发删除对象,如果代理对象挂钩到属性访问,__ nonzero__或__len__方法并触发删除.然后,线程可以导致竞争条件,其中上述函数将返回True,您仍然必须考虑对象上的操作可能引发ReferenceError.

如果订单不重要,我在这里使用weakref.WeakSet() object;当循环遍历这些时,您将获得实时对象;已经取消引用为你修剪的死亡参考文献,没有竞争条件的风险.

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


我最近重新拾起了计算机视觉,借助Python的opencv还有face_recognition库写了个简单的图像识别demo,额外定制了一些内容,原本想打包成exe然后发给朋友,不过在这当中遇到了许多小问题,都解决了,记录一下踩过的坑。 1、Pyinstaller打包过程当中出现warning,跟d
说到Pooling,相信学习过CNN的朋友们都不会感到陌生。Pooling在中文当中的意思是“池化”,在神经网络当中非常常见,通常用的比较多的一种是Max Pooling,具体操作如下图: 结合图像理解,相信你也会大概明白其中的本意。不过Pooling并不是只可以选取2x2的窗口大小,即便是3x3,
记得大一学Python的时候,有一个题目是判断一个数是否是复数。当时觉得比较复杂不好写,就琢磨了一个偷懒的好办法,用异常处理的手段便可以大大程度帮助你简短代码(偷懒)。以下是判断整数和复数的两段小代码: 相信看到这里,你也有所顿悟,能拓展出更多有意思的方法~
文章目录 3 直方图Histogramplot1. 基本直方图的绘制 Basic histogram2. 数据分布与密度信息显示 Control rug and density on seaborn histogram3. 带箱形图的直方图 Histogram with a boxplot on t
文章目录 5 小提琴图Violinplot1. 基础小提琴图绘制 Basic violinplot2. 小提琴图样式自定义 Custom seaborn violinplot3. 小提琴图颜色自定义 Control color of seaborn violinplot4. 分组小提琴图 Group
文章目录 4 核密度图Densityplot1. 基础核密度图绘制 Basic density plot2. 核密度图的区间控制 Control bandwidth of density plot3. 多个变量的核密度图绘制 Density plot of several variables4. 边
首先 import tensorflow as tf tf.argmax(tenso,n)函数会返回tensor中参数指定的维度中的最大值的索引或者向量。当tensor为矩阵返回向量,tensor为向量返回索引号。其中n表示具体参数的维度。 以实际例子为说明: import tensorflow a
seaborn学习笔记章节 seaborn是一个基于matplotlib的Python数据可视化库。seaborn是matplotlib的高级封装,可以绘制有吸引力且信息丰富的统计图形。相对于matplotlib,seaborn语法更简洁,两者关系类似于numpy和pandas之间的关系,seabo
Python ConfigParser教程显示了如何使用ConfigParser在Python中使用配置文件。 文章目录 1 介绍1.1 Python ConfigParser读取文件1.2 Python ConfigParser中的节1.3 Python ConfigParser从字符串中读取数据
1. 处理Excel 电子表格笔记(第12章)(代码下载) 本文主要介绍openpyxl 的2.5.12版处理excel电子表格,原书是2.1.4 版,OpenPyXL 团队会经常发布新版本。不过不用担心,新版本应该在相当长的时间内向后兼容。如果你有新版本,想看看它提供了什么新功能,可以查看Open