资讯专栏INFORMATION COLUMN

关于对象,我犯了一个错误

pepperwang / 798人阅读

摘要:在我的一个业务逻辑代码中,我不幸需要编写以下类这里我们用抽象的表示这是两个没有什么问题的对象,不过在创建的实例时,会让自己的属性指向一个的实例,而中的属性又指向该实例所以我们可以像下面这样访问这样能够使得拥有的控制权,也同时使得拥有的控制权

在我的一个业务逻辑代码中,我不幸需要编写以下类(这里我们用抽象的A, B, C表示)

class A:
   value = 0
   def __init__(self, b):
                self.b = b
    
   def set_1(self):
        self.value = 1
        
class B:
        
    def __init__(self):
        pass
        
    def reset(self):
        self.a = A(self)
 

这是两个没有什么问题的对象,不过在创建B的实例时,会让自己的属性a指向一个A的实例,而a中的属性b又指向该B实例
所以我们可以像下面这样访问:

b = B()
a = b.a
assert b.a.b is b
assert b.a.b.a is a

这样能够使得b拥有a的控制权,也同时使得a拥有b的控制权。

但是当我试图用一个类C来代理实例b时,却犯了一个错误

class C:
    b = B()
    a = b.a
 
    def __init__(self):
        pass
 
    def read_a(self):
        return self.b.a.value
 
 
c = C()
assert c.read_a() == 0
c.a.set_1()
assert c.read_a() == 1
 
c.b.reset()
assert c.read_a() == 0
assert c.a == 0  # AssertionError

为什么这里我会脑子抽断言 c.a == 0呢?
因为我主观地认为这里实例b执行了reset函数,于是重新实例化了属性b.a=A(self)
那么a在实例过程中,会让a.value = 0
所以 c.b.a.value == 0
而我们的c.a = b.a
所以c.a.value == c.b.a.value == 0
几乎完美的推理!!!

但是我忽略了,这里的c.a is not c.b.a !!!
原因如下:
假设一开始实例化A, B 为 a1, b1
c.a -> a1
c.b -> b1
那么当b1.reset() 的时候,a是重新实例化的一个A对象,用JAVA的话来说,就是重新new 了一个A
b1.a -> a2
故c.b.a == c.b1.a == a2
而c.a == a1
a1.value在a1.set_1()之后,赋值为 1
a2.value在b1.reset()之后,赋值为 0
所以断言错误

记录这个错误警告自己在今后的编码过程中不要一味主观地用数学观点,而要弄清楚具体对象。

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/41083.html

相关文章

  • 【debug】事件绑定代码中的一个低级错误导致的内存泄漏

    摘要:静下来想了想发现我犯了一个低级错误。上面的代码中函数是在这个函数闭包中申明的,在这个函数执行完毕后,由于它被绑上了事件,引用并不为,所以没有被回收。 最近写一个web应用的图片上传功能,里面有这么个场景:点击上传按钮,呼出file input框,选择完图片进行前端压缩然后上传,完毕后将返回的图片链接展示给用户。这个功能很常见,但是在这里却翻了船,所以专门记录一下这个bug。 我是这么写...

    XboxYan 评论0 收藏0
  • laraval模板方法设计模式实现服务容器

    摘要:当我执行代码首次失败时,我去网上搜寻答案,他们说,你这种实现模式,就在注册服务时,应该注册抽象类,而不是接口类。 1、第一点,首先说明设计模式跟实现服务容器没关系 之所以采用这个标题,是因为自己当初犯了这种错误,希望新学laravel的人不要犯这种跟我一样的错误。 2、我定义了接口,同时抽象类继承接口,其他具体实现类继承抽象类。 当我执行代码首次失败时,我去网上搜寻答案,他们说,你这种...

    newsning 评论0 收藏0
  • 填坑之PHP的yield和协程在一起的日子里(二)

    摘要:粗暴地说上面的过程就算是协程的基本概念。多线程和多进程都是操作系统参与的调度,而协程是用户自主实现的调度,协程的关键点实际上是用户层实现自主调度,大概有翻身农奴把歌唱的意思。 首先是,这是我第一次把公众号文章复制粘贴到sf.gg来。 其次是,很久很久之前,我挖了一个yield的一个坑,自己挖的坑自己填,不然迟早会把自己埋掉。 最后是,如果想看之前那个坑,请发送yield给文章末尾的公众...

    Scorpion 评论0 收藏0
  • 记录manjaro linux下起angular + spring + nginx 项目环境

    摘要:我用的是内核是,有些东西和不太一样所以在起环境时遇到了一些没见过的问题。安装与这俩我尝试下载安装官网上的包,但均以失败告终,原因不明,还好自带的软件库有最新版,可以很方便地进行安装。甚至还有检查最新版本依赖的工具,省下了手动更新的麻烦。 我用的linux是manjaro,内核是arch,有些东西和ubantu,deepin不太一样,所以在起环境时遇到了一些没见过的问题。 安装nodej...

    littlelightss 评论0 收藏0

发表评论

0条评论

pepperwang

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<