鱼C论坛

 找回密码
 立即注册
查看: 960|回复: 10

[已解决]del 仅删除变量还是变量和其指定对象一起删除?

[复制链接]
发表于 2022-3-21 17:32:38 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

x
>>> a  = dict.fromkeys('吕布',990)
>>> a
{'吕': 990, '布': 990}
>>> b = a
>>> b
{'吕': 990, '布': 990}
>>> del a
>>> b
{'吕': 990, '布': 990}

如上述代码所示,a,b变量共同指向字典{'吕': 990, '布': 990},
当清除a时,为啥对b不产生影响啊?a和b不是指向同一指定的字典(存储地址)么?
要是del能够把变量和其指定对象一起干掉的话,那么在干掉a的同时b也应该被干掉吧?

请各位前辈教一下python是如何储存和调用数据的,变量如何赋值给指定对象并且获取的。
晚辈在此感激不尽!
最佳答案
2022-3-21 23:58:39
本帖最后由 阿奇_o 于 2022-3-22 00:32 编辑

我们无法直接使用"对象",而是通常是用一个"字符名/变量名"去使用(引用)它
—— 对象其实是一个抽象的概念,一个对象 一旦被创建就至少包含:对象的type, value, 和 id
以及与之绑定的名字name(基本上都有,以方便"以名唤之";当然也可没有,那是unbound object...)

del a 其实只是解除了 a 这个名字与那个字典对象之间的绑定关系——断开了这种绑定关系,对于该对象来说,就是"引用减1"。
你这里 一开始 a, b 都 绑定到 那个字典对象上(而不是b绑到a上)。 del a 只是解除了a与之的引用关系,b 还是绑定着的。

除了最常见的赋值语句,会创建这种绑定/引用关系,def, class, import 等语句,都可以建立这种 名字name → 对象object 的绑定关系。
  1. >>> def func():   # def语句 既创建了一个函数对象function object,也同时将 func 这名字 绑定到该函数对象上
  2.         print("Hey")


  3. >>> func   # 函数对象(以名唤之)
  4. <function func at 0x000001F71ACDD1F8>
  5. >>> func()   # 以名唤之,然后执行其函数体
  6. Hey
  7. >>> del func   # 解除绑定(所绑定的函数对象会"引用减1";若引用为0,将进入"垃圾回收机制")

  8. >>> func()   # 已解除绑定,无法再以名唤之
  9. Traceback (most recent call last):
  10.   File "<pyshell#9>", line 1, in <module>
  11.     func()
  12. NameError: name 'func' is not defined
  13. >>>
复制代码
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2022-3-21 17:42:59 | 显示全部楼层
del 是把对象的引用减 1,当对象的引用为 0 时就会被垃圾回收机制回收。

通过 sys模块 的 getrefcount 函数可以获取对象的引用:

>>> a = [1,2, 4, 5]
>>> import sys
>>> sys.getrefcount(a[1:])
1
>>> import sys
>>> a  = dict.fromkeys('吕布',990)
>>> sys.getrefcount(a)            # 引用为 2 是因为在调用 getrefcount 的时候也用到了 a
2
>>> b = a
>>> sys.getrefcount(a)
3
>>> sys.getrefcount(b)
3
>>> del a
>>> sys.getrefcount(b)
2
>>>
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2022-3-21 20:24:00 | 显示全部楼层
isdkz 发表于 2022-3-21 17:42
del 是把对象的引用减 1,当对象的引用为 0 时就会被垃圾回收机制回收。

通过 sys模块 的 getrefcount  ...

前辈,对象的引用和对象的赋值是什么关系
是不是对象的赋值是引用的一种
对象是字典{'吕布':990}
a = {'吕布':990}引用一次(把对象赋值给a)
调用getrefcount(a)引用第二次
b = a引用第三次(把对象赋值给b)
del a删除一次引用
故字典被引用两次
这么理解对么?
为什么调用getrefcount(a)算引用一次,调用getrefcount(b)的时候不算引用呢
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2022-3-21 20:28:16 | 显示全部楼层
李二蛋 发表于 2022-3-21 20:24
前辈,对象的引用和对象的赋值是什么关系
是不是对象的赋值是引用的一种
对象是字典{'吕布':990}

调用 getrefcount(b) 的时候也算呀,只不过这个调用完就没有这个引用了,

所以调用 getrefcount(a) 结束这个引用就被释放减一了,所以调用 getrefcount(b) 的时候就还是 2
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2022-3-21 23:58:39 | 显示全部楼层    本楼为最佳答案   
本帖最后由 阿奇_o 于 2022-3-22 00:32 编辑

我们无法直接使用"对象",而是通常是用一个"字符名/变量名"去使用(引用)它
—— 对象其实是一个抽象的概念,一个对象 一旦被创建就至少包含:对象的type, value, 和 id
以及与之绑定的名字name(基本上都有,以方便"以名唤之";当然也可没有,那是unbound object...)

del a 其实只是解除了 a 这个名字与那个字典对象之间的绑定关系——断开了这种绑定关系,对于该对象来说,就是"引用减1"。
你这里 一开始 a, b 都 绑定到 那个字典对象上(而不是b绑到a上)。 del a 只是解除了a与之的引用关系,b 还是绑定着的。

除了最常见的赋值语句,会创建这种绑定/引用关系,def, class, import 等语句,都可以建立这种 名字name → 对象object 的绑定关系。
  1. >>> def func():   # def语句 既创建了一个函数对象function object,也同时将 func 这名字 绑定到该函数对象上
  2.         print("Hey")


  3. >>> func   # 函数对象(以名唤之)
  4. <function func at 0x000001F71ACDD1F8>
  5. >>> func()   # 以名唤之,然后执行其函数体
  6. Hey
  7. >>> del func   # 解除绑定(所绑定的函数对象会"引用减1";若引用为0,将进入"垃圾回收机制")

  8. >>> func()   # 已解除绑定,无法再以名唤之
  9. Traceback (most recent call last):
  10.   File "<pyshell#9>", line 1, in <module>
  11.     func()
  12. NameError: name 'func' is not defined
  13. >>>
复制代码
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 1 反对 0

使用道具 举报

 楼主| 发表于 2022-3-23 09:26:18 | 显示全部楼层
isdkz 发表于 2022-3-21 20:28
调用 getrefcount(b) 的时候也算呀,只不过这个调用完就没有这个引用了,

所以调用 getrefcount(a) 结 ...

wuwuwuwuwu
我好笨啊
前辈我还是没懂
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2022-3-23 09:42:55 | 显示全部楼层
阿奇_o 发表于 2022-3-21 23:58
我们无法直接使用"对象",而是通常是用一个"字符名/变量名"去使用(引用)它
—— 对象其实是一个抽象的概 ...

厉害厉害,懂啦懂啦~~牛牛牛
请问前辈咱现在说的这种对于对象的加减一引用的方式
适用于所有类型的对象么
这个复制,深复制有什么关系
>>> x = 'Fishc'
>>> y = x
>>> x is y
True

>>> x = [1,2,3]
>>> y = x
>>> x is y
True
>>> q = [1,2,3]
>>> x is q
False
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2022-3-23 09:54:28 | 显示全部楼层
阿奇_o 发表于 2022-3-21 23:58
我们无法直接使用"对象",而是通常是用一个"字符名/变量名"去使用(引用)它
—— 对象其实是一个抽象的概 ...

前辈,is 和is not同一性运算符用来判断二者的id值是否相等
能否判断二者引用的为同一对象?
二者的id值相同是否可以认为二者引用的为同一对象?
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2022-3-23 18:56:11 | 显示全部楼层
本帖最后由 阿奇_o 于 2022-3-23 19:08 编辑
李二蛋 发表于 2022-3-23 09:42
厉害厉害,懂啦懂啦~~牛牛牛
请问前辈咱现在说的这种对于对象的加减一引用的方式
适用于所有类型的对象 ...


这是最底层、最基本的关于对象的规则,是适用于所有对象的。

浅复制、深复制,也比较好理解,具体可以自己搜例子看,
简单来说,

浅复制,就是将引用、将绑定关系绑到一个新的"容器"上,容器里面还是继续用旧的(不关心容器里面的对象,这样就可能导致容器里的对象可能被修改)。
你甚至可以将"浅复制"不看做是"复制",因为它只是"换了个壳"——id(qcopy)是不同了,但里面的 id(qcopy[0]) 和 id(x[0]是同一个对象)。

深复制,是将容器及其里面所有对象,都拷贝一份到另一处内存地址上,这是一个全新的、独立的容器对象(你理解一下这里的"独立"意味着什么?)。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2022-3-23 19:04:13 | 显示全部楼层
李二蛋 发表于 2022-3-23 09:54
前辈,is 和is not同一性运算符用来判断二者的id值是否相等
能否判断二者引用的为同一对象?
二者的id ...

是的。id(x) 返回的就是 x 所指向的对象的 唯一标识符identity。 是唯一的。
id相同,就是同一个对象。 a is b --> True

而像 == > < != 这些是比较运算符,取决于 左右要比较的对象的类中所定义相关方法,
如 __equal__ 通常是定义 同类型之间 比较对象的value是否相等。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 1 反对 0

使用道具 举报

 楼主| 发表于 2022-3-23 19:10:47 | 显示全部楼层
阿奇_o 发表于 2022-3-23 19:04
是的。id(x) 返回的就是 x 所指向的对象的 唯一标识符identity。 是唯一的。
id相同,就是同一个对象。  ...

感谢前辈
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2024-5-20 08:45

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表