首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >在实例赋值后,垃圾收集不识别类的del。

在实例赋值后,垃圾收集不识别类的del。
EN

Stack Overflow用户
提问于 2014-02-25 22:21:47
回答 2查看 386关注 0票数 1

为了测试目的,我正在创建临时类,我想删除这些类(在其他测试方法运行之前)。问题是,即使在运行垃圾收集之后,[superclass].__subclasses__()仍然列出已删除的类。

下面是我的测试方法:

代码语言:javascript
复制
class Apple(Fruit):
    @staticmethod
    def mass(size):
        return size

class Orange(Fruit):
    @staticmethod
    def mass(size):
        return size

try:
    Apple()
    Orange()
    a1 = Apple(type='fuji')
finally:
    if 'a1' in locals():
        print 'del a1'
        del a1
    print gc.get_referrers(Apple)
    print gc.get_referrers(Orange)
    del Apple
    del Orange
    print Fruit.__subclasses__()
    gc.collect()
    print Fruit.__subclasses__()

产出如下:

代码语言:javascript
复制
del a1
[<frame object at 0xabcdef0>, (<class 'Apple'>, <class 'Fruit'>, <type 'object'>), <Apple object at 0x4443331>, {'a1': <Apple object at 0x4443331, 'self': <FruitTests testMethod=test_pass_Fruit_core>, 'Orange': <class 'Orange'>, 'Apple': <class 'Apple'>}]    
[<frame object at 0xabcdef0>, (<class 'Orange'>, <class 'Fruit'>, <type 'object'>), {'a1': <Apple object at 0x4443331, 'self': <FruitTests testMethod=test_pass_Fruit_core>, 'Orange': <class 'Orange'>, 'Apple': <class 'Apple'>}]
[<class 'Apple'>, <class 'Orange'>]
[<class 'Apple'>, <class 'Orange'>]

所有涉及的类都没有显式定义的__del__(),尽管Fruit确实在Fruit.mass()上使用了__metaclass__ = abc.ABCMeta@abc.abstractmethod装饰器。

其余的类引用与将Fruit实例赋值给一个变量有关:如果删除包含a1的所有行,则最终的Fruit.__subclasses__()返回[] --尽管裸构造函数Apple()仍在运行。

这对我来说是个问题,因为另一个测试涉及到水果交互作用(调用相关的待测试方法blends()),它使用Fruit.__subclasses__()调用来检查不同类型Fruit的组合。我没有费心定义与这些测试类的交互,这让blends()很困惑。

任何提示,为什么这些参考资料停留在附近,将不胜感激。

编辑:如果我在gc.collect()之后调用gc.collect(Apple),我会得到一个"UnboundLocalError:局部变量'Apple‘在赋值前引用的“UnboundLocalError定义了许多方法,其中包含了"@classmethod”和"@property“装饰器,并引用了另一个类,该类处理”复合()“.

在垃圾收集之后,gc.get_referrers(Fruit.__subclasses__()[0])返回

代码语言:javascript
复制
[{'a1': <Apple object at 0x4443331>, 'self': <FruitTests testMethod=test_pass_Fruit_core>, 'Orange': <class 'Orange'>, 'Apple': <class 'Apple'>}, <Apple object at 0x4443331>, (<class 'Apple'>, <class 'Fruit'>, <type 'object'>)]

编辑:当我只运行这一种测试方法时,问题就会发生。(当我排队进行多个测试时,也会发生这种情况。)我尝试从命令行重新启动IDE (PyCharm)并运行"./manage.py e.py测试FruitTests.test_pass_Fruit_core“。虽然特定的内存地址不同,但所有情况都会产生相同的结果。当地人()被直接调用--我在任何地方都没有它的别名。

编辑:定义水果的整个模块:

代码语言:javascript
复制
from abc import abstractmethod, ABCMeta


class Fruit(object):
    __metaclass__ = ABCMeta

    def __init__(self, **kwargs):
        super(Fruit, self).__init__()

    @abstractmethod
    def mass(self, size):
        raise NotImplementedError

在测试方法中,test_pass_Fruit_core()、"a1 = Apple()“和"a1 = Apple(type='fuji')”产生相同的结果。将分配任务删除到"a1“并没有什么区别,但是如果我放弃对”局部变量()“的调用,垃圾收集就会像预期的那样工作--在方法的末尾,苹果不再是果树的子类。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2014-02-25 23:42:23

持久引用是在对局部变量()的调用中创建的。为了保证"del a1“不生成错误,如果在"try:”块中创建了一个错误,则在块之前分配"a1 = None“,并跳过对局部变量的调用。

最后,工作代码如下。与上面的第一个代码块比较:类Apple(果树):@staticmethod def质量( size ):返回大小

代码语言:javascript
复制
class Orange(Fruit):
    @staticmethod
    def mass(size):
        return size

a1 = None
try:
    Apple()
    Orange()
    a1 = Apple(type='fuji')
finally:
    del a1
    print gc.get_referrers(Apple)
    print gc.get_referrers(Orange)
    del Apple
    del Orange
    print Fruit.__subclasses__()
    gc.collect()
    sc = Fruit.__subclasses__()
    print sc
    if len(sc) > 0:
        print 42, gc.get_referrers(sc[0])
票数 0
EN

Stack Overflow用户

发布于 2014-02-25 23:16:00

在垃圾收集环境中,对象的生命时间不是您的责任。正因为如此,你不应该依赖这个。单元测试应该测试您的业务逻辑,每个单元测试应该测试一个单元的职责。对象生命时间不可能是他们的责任,如果您的逻辑依赖于它,那么要么您使用了错误的环境,要么您滥用了您当前的环境。

也许尝试在您的实现中引入一个“活动”Fruit的概念,使用Pool或/和Factory之类的模式。如果要从“活动”对象列表中删除一个对象,就不必担心GS的“不确定性”。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/22027521

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档