鱼C论坛

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

[已解决]新人求助 类对象 实例对象的问题

[复制链接]
发表于 2017-5-7 16:23:40 | 显示全部楼层 |阅读模式

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

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

x
本帖最后由 jiangxibian 于 2017-5-7 23:22 编辑

代码如下:

class Test1():
    a=[]
    def func(self,n):
        self.a.append(n)

class Test2():
    b=1

结果如下:

>>> a=Test1()
>>> b=Test1()
>>> c=Test2()
>>> d=Test2()
>>> a.func(1)
>>> a.a
[1]
>>> b.a
[1]
>>> c.b=2
>>> d.b
1
>>>

萌新看不懂啊,按照我的理解,a.func(1)修改的不应该是自己的self.a吗,为什么b的值也改了呢
查了一下地址,发现a.a b.a Test1.a都是一样的,所以问题是知道了,但是为什么会这样呢?按照本来的理解
他不应该和下面c d的情况是一样的吗?在哪里理解错了呢?
-----------------------------------------------------------------------------------------------------------------------分割线
来改一下,把问题写的清楚点:
code:

class Test1():
    a=[]
    b=1
    def func(self,n):
        self.a.append(n)

运行:
>>> a=Test1()
>>> b=Test1()
>>> a.a
[]
>>> b.a
[]
>>> a.b
1
>>> b.b
1
>>> a.func(1)
>>> a.a
[1]
>>> b.a
[1]

>>> a.b=2
>>> a.b
2
>>> b.b
1


-----------------------------------------------------------------------------------------------------------------------分割线

又有新想法,修改了下代码发现了有趣的事:

class Test1():
    a=1
    b=1
    def func(self,n):
        self.a+=1

运行:
>>> a=Test1()
>>> b=Test1()
>>> a.a
1
>>> b.a
1
>>> a.b
1
>>> b.b
1
>>> a.func(1)
>>> a.a
2
>>> b.a
1


值改变了,所以说  是因为列表的原因才导致之前的代码  所有对象的该属性都在同一个地址?有没有大佬能帮忙讲一下具体的原理呢

-----------------------------------------------------------------------------------------------------------------------分割线
补充一下终于让我看懂了的地址吧:https://zhidao.baidu.com/question/2117861326947340307.html     下面那个其他回答
最佳答案
2017-5-7 19:34:34
英语不好,F1看文档半天也看不懂

我自己这么理解:
Test1.a是一个类变量,所以代码只要运行起来就会在内存中保存Test1.a = []

然后当你实例化对象的时候,会去复制Test1.a,这里应该是浅拷贝,所以只是把引用给复制了过来

所以当类变量是引用类型的时候,每个实例都会去复制这个类变量的引用,所以每个实例对象中存放的其实是指向同一个引用对象的

你这里就是指向同一个列表
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2017-5-7 18:26:07 | 显示全部楼层
试试改成self.a = []
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2017-5-7 19:34:34 | 显示全部楼层    本楼为最佳答案   
英语不好,F1看文档半天也看不懂

我自己这么理解:
Test1.a是一个类变量,所以代码只要运行起来就会在内存中保存Test1.a = []

然后当你实例化对象的时候,会去复制Test1.a,这里应该是浅拷贝,所以只是把引用给复制了过来

所以当类变量是引用类型的时候,每个实例都会去复制这个类变量的引用,所以每个实例对象中存放的其实是指向同一个引用对象的

你这里就是指向同一个列表
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2017-5-7 20:39:54 | 显示全部楼层

这个直接报错:
Traceback (most recent call last):
  File "C:\Users\WokeParis\Desktop\新建文件夹\test_3_1.py", line 3, in <module>
    class Test1():
  File "C:\Users\WokeParis\Desktop\新建文件夹\test_3_1.py", line 4, in Test1
    self.a=[]
NameError: name 'self' is not defined
>>> 咔咔
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2017-5-7 20:46:52 | 显示全部楼层
因为你的 Test1 里的 a 是类对象的属性
而你的 a.func 则是实例对象的方法里操作的是类的属性。
类里的属性是会根据实例化的方法或者属性而跟着改变的。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2017-5-7 20:47:06 | 显示全部楼层
zlj19931010 发表于 2017-5-7 19:34
英语不好,F1看文档半天也看不懂

我自己这么理解:

那Test2类呢,c.b=2 但是d.b却为1  从结果的角度出发,我只能理解为:a=[]对象实例化的时候是一个引用,不管是类还是对象,都是一个内存地址,但b=1实例化的每个对象都有一个单独的地址。
but    why?
难道就这么死记硬背了?
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2017-5-7 21:00:45 | 显示全部楼层
Leopoldfire 发表于 2017-5-7 20:46
因为你的 Test1 里的 a 是类对象的属性
而你的 a.func 则是实例对象的方法里操作的是类的属性。
类里的属 ...

首先谢谢回复,但是读了好几遍依然有些看不懂啊,请看修改后的code,我感觉a和b应该是一样的啊,只不过一个是通过方法修改的,一个是直接修改的,为什么结果会不同呢
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2017-5-7 22:00:26 | 显示全部楼层
jiangxibian 发表于 2017-5-7 21:00
首先谢谢回复,但是读了好几遍依然有些看不懂啊,请看修改后的code,我感觉a和b应该是一样的啊,只不过一 ...

你首先知道 类对象和实例对象是什么?
区别在哪?
这些题都会懂的。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2017-5-7 22:39:04 | 显示全部楼层
Leopoldfire 发表于 2017-5-7 22:00
你首先知道 类对象和实例对象是什么?
区别在哪?
这些题都会懂的。

可能是我标题有误,那是我刚发现问题时的思考方向,现在看来是有问题的,类对象和实例对象我还是分得清楚地,这个问题也不是类对象和实例对象的问题,我所有的例子中都没有用到类对象,现在的问题是,为什么在类中的列表变量在所有对象中都是一个地址而数字(我不知道该怎么说,又不是整形啥的)变量是不同的地址?
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2017-5-7 22:46:58 | 显示全部楼层
zlj19931010 发表于 2017-5-7 19:34
英语不好,F1看文档半天也看不懂

我自己这么理解:

第一次看这个貌似没看懂,
现在感觉这条是对的?   但是a=[]和a=1在在实例化的过程中为什么会有区别呢?记住就好了么?
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2017-5-8 16:53:29 | 显示全部楼层
本帖最后由 zlj19931010 于 2017-5-8 16:58 编辑
jiangxibian 发表于 2017-5-7 22:46
第一次看这个貌似没看懂,
现在感觉这条是对的?   但是a=[]和a=1在在实例化的过程中为什么会有区别呢? ...

  1. >>> a = 1
  2. >>> b = a
  3. >>> a += 1
  4. >>> a
  5. 2
  6. >>> b
  7. 1
  8. >>> type(a)
  9. <class 'int'>
  10. >>> type(b)
  11. <class 'int'>
  12. >>> a.__repr__
  13. <method-wrapper '__repr__' of int object at 0x0000000056B0A480>
  14. >>> b.__repr__
  15. <method-wrapper '__repr__' of int object at 0x0000000056B0A460>
复制代码

Numeric Types 类型的赋值,也就是b = a, a和b两个是不同的对象了,python自己做了重新创建对象的操作

  1. >>> a = []
  2. >>> b = a
  3. >>> type(a)
  4. <class 'list'>
  5. >>> type(b)
  6. <class 'list'>
  7. >>> a.__repr__
  8. <method-wrapper '__repr__' of list object at 0x00000000030FC0C8>
  9. >>> b.__repr__
  10. <method-wrapper '__repr__' of list object at 0x00000000030FC0C8>
复制代码

Sequence Types 类型的赋值,b = a,并没有创建新对象,两个指向一样的

所以:
  1. >>> a1 = a()
  2. >>> a2 = a()
  3. >>> a1.a
  4. []
  5. >>> a1.a.__repr__
  6. <method-wrapper '__repr__' of list object at 0x000000000016EE48>
  7. >>> a2.a.__repr__
  8. <method-wrapper '__repr__' of list object at 0x000000000016EE48>
  9. >>>
复制代码

每个实例对象指向的是同一个类变量

到这里,我也发现了,其实造成你这种现象主要是因为 值类型 和 引用类型 在赋值的时候采取的策略不同
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

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

本版积分规则

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

GMT+8, 2024-5-19 01:35

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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