网上流传最广的 Python 单例模式竟然是有问题的?

2022-06-23 17:35:46 +08:00
 wuwukai007
class AppConfig:
    def __new__(cls, *args, **kwargs):
        if not hasattr(cls,'_instance'):
            cls._instance=super(AppConfig,cls).__new__(cls)
        return cls._instance

app = AppConfig()
app.name = '单例模式'
del app
app2 = AppConfig()
print("app2 name=",app2.name)
5173 次点击
所在节点    Python
26 条回复
leavic
2022-06-23 17:43:32 +08:00
我今天才知道 python 还有 del app 这种写法
dcsuibian
2022-06-23 17:47:04 +08:00
作用域不同。
dcsuibian
2022-06-23 17:53:38 +08:00
似乎说法不太对。app 和 AppConfig 类的_instance 都引用一个东西,app 这个引用消失了,但引用的东西没消失
Hstar
2022-06-23 17:53:54 +08:00
因为 del app 并没有删除对象,只是删掉了这个对象在此的引用
cz5424
2022-06-23 17:55:14 +08:00
del app 并且 del app. _instance 试试
wuwukai007
2022-06-23 17:59:55 +08:00
@cz5424 这个代码一致性就破坏了
ChrisFreeMan
2022-06-23 18:05:46 +08:00
你要手动实现__del__
wuwukai007
2022-06-23 18:06:32 +08:00
@ChrisFreeMan 试过了,不行的,你试试看?__del__ 只有在程序结束后才会调用,del 不会调用的
nyxsonsleep
2022-06-23 18:13:29 +08:00
这个问题如果用过 pyqt 应该会映像深刻。。。
个人理解 del 实质上没有删除对象的存在,有时会导致 pyqt 删除 gui 时出问题。
deplivesb
2022-06-23 18:13:54 +08:00
python 里面的 del 可和 c 系列的 del 不是一个作用,del 也不会调用 __del__
fatigue
2022-06-23 18:14:24 +08:00
_instance 是挂在类下面的, 你 AppConfig()的时候把这个引用返回给你,你 del 的时候把这个引用删除,_instance 一直都在,下次 AppConfig()再返回给你
ChrisFreeMan
2022-06-23 18:27:20 +08:00
__del__试了下确实不行,这样,其实你是把单例对象赋值给了类,其实那个单例对象是个类对象
你用反射检查一下有没有单例对象再删除。
class Test:
def __new__(cls, *args, **kwargs):
if not hasattr(cls, '_instance'):
cls._instance = super().__new__(cls)
return cls._instance


app = Test()
app.name = 'some thing1'
if hasattr(Test, '_instance'):
del Test._instance
app2 = Test()
print(app2.name)
ysy950803
2022-06-23 18:41:41 +08:00
依附于类,而不是对象。
jinliming2
2022-06-23 21:49:39 +08:00
单例模式允许删除重新创建吗?
我理解的单例模式,一个类只能有一个对象,其他人来访问的时候可以直接拿到这个对象。
但没听说过还能有人可以删除掉这个单例对象,然后让重新创建一个……?
ospider
2022-06-23 22:15:25 +08:00
除了面试,没用过单例模式……
ruanimal
2022-06-23 22:55:37 +08:00
lz 没理解 del 和 Python 对象,4 楼的是正解
zxCoder
2022-06-23 23:05:41 +08:00
@jinliming2 我也没听说过,之前学过的都是你这种说法
xuboying
2022-06-23 23:49:28 +08:00
好像 del 的行为只是一个请求,实际删除 instance 的时机是不可控的。即使用了 weakref ,在官方例子中还调用了 gc 回收,才能强制请求删除。
还有一个问题是不确定这个行为在非 cPython 的环境下是不是一致的。
lanlanye
2022-06-24 08:18:58 +08:00
Python 最流行的单例模式难道不是直接初始化然后 import ?
InvincibleDream
2022-06-24 09:14:52 +08:00

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/861715

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX