Python unittest 模块关于对象的类属性和实例属性的异常现象

发布于 2022-09-06 10:45:39 字数 3060 浏览 41 评论 0

在编写模块的过程中,我写到以下类和方法(这里用 AB 抽象表示):

class A:
    pass


class B:
    prop_list = [None]

    def __init__(self):
        self.a = A()
        self.prop_list[0] = self.a

作用就是类 B 的属性 aA 的一个实例,而 B.prop_list 中包含这个实例。

然后写单元测试的时候,写了如下测试(简化模型):

import unittest

class TestFirst(unittest.TestCase):
    b = B()
    assert b.prop_list[0] is b.a

    def test_func1(self):
        assert self.b.prop_list[0] is self.b.a
        
unittest.main()

作用就是判断 B 的实例 b 中的属性 a 就是它 prop_list 中的 a,测试通过

但是当我添加一个一模一样的测试时候:

import unittest

class TestFirst(unittest.TestCase):
    b = B()
    assert b.prop_list[0] is b.a

    def test_func1(self):
        # !!! AssertionError
        assert self.b.prop_list[0] is self.b.a


class TestSecond(unittest.TestCase):
    b = B()
    assert b.prop_list[0] is b.a

    def test_func1(self):
        assert self.b.prop_list[0] is self.b.a
        
unittest.main()

却发现 AssertionError !

我尝试利用 print 函数把每个属性打印出来:

class TestFirst(unittest.TestCase):
    b = B()
    print('test_1:')
    print(b.a)
    print(b.prop_list[0])
    # assert b.prop_list[0] is b.a

    def test_func1(self):
        print('func1:')
        print(self.b.a)
        print(self.b.prop_list[0])
        # assert self.b.prop_list[0] is self.b.a


class TestSecond(unittest.TestCase):
    b = B()
    print('test_2:')
    print(b.a)
    print(b.prop_list[0])
    # assert b.prop_list[0] is b.a

    def test_func2(self):
        print('func2')
        print(self.b.a)
        print(self.b.prop_list[0])
        # assert self.b.prop_list[0] is self.b.a

得到以下结果:

test_1:
<__main__.A object at 0x000001F07CD7D7F0>
<__main__.A object at 0x000001F07CD7D7F0>
test_2:
<__main__.A object at 0x000001F07CD7D828>
<__main__.A object at 0x000001F07CD7D828>
func1:
<__main__.A object at 0x000001F07CD7D7F0> 
<__main__.A object at 0x000001F07CD7D828>  // 这里居然不是 0x000001F07CD7D7F0
.func2
<__main__.A object at 0x000001F07CD7D828>
<__main__.A object at 0x000001F07CD7D828>
.
----------------------------------------------------------------------
Ran 2 tests in 0.002s
  • 为什么 TestFirst 实例方法 test_func1self.b.prop_list[0] 和自己的 self.b.a 不是同一个对象,而和 TestSecond 实例方法 test_func2 中的 self.b.prop_list[0] 一样呢?

另外,如果我把 class Bprop_list 当作实例属性,在初始化函数 __init__() 中声明:

class A:
    pass


class B:
    def __init__(self):
        self.a = A()
        self.prop_list= [self.a]

再次运行上述测试时候,发现可以通过。

这两种方式为什么会有差别,这里面还有其他坑没有?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

永不分离 2022-09-13 10:45:39

是這樣的:

這裡從頭到尾的 prop_list 都是同一個!

所以 TestSecondb 被初始化的時候, 就將 prop_list[0] 的值設定為 TestSecondb.a 的值了, 而 test_func1 又在之後被調用, 此時prop_list[0] 的值自然跟 TestFirstb.a 的值不同, 而是與 TestSecond 中的 b.a 相同。

補充一下, 為什麼 prop_list 為什麼都是同一個呢, 因為他是 B 的類別屬性, 會自然成為每個 B 實例的屬性, 而且他從頭到尾沒有在任何 B 的實例中被重新賦值過(他的第零個元素 prop_list[0] 倒是有被重新賦值過), 所以他 always 是同一個人。


我回答過的問題: Python-QA

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文