鱼C论坛

 找回密码
 立即注册
查看: 2520|回复: 12

[已解决]Python 关于类的一个问题

[复制链接]
发表于 2021-2-2 10:09:37 | 显示全部楼层 |阅读模式

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

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

x
本帖最后由 Peteryo01223 于 2021-2-2 10:11 编辑

我的问题:标准代码和运行结果,如下。运行结果第16行和17行,我分别输入了1和2,但未对结果产生影响,还是20。其原因,是类的属性(即:变量值)不能被运行程序后的赋值所改变,是吗?请帮我确认一下原因。

标准代码:
  1. class Rectangle:
  2.     length = 5
  3.     width = 4

  4.     def setRect(self):
  5.         print('请输入举行的长和宽。。。')
  6.         self.length = float(input('长:'))
  7.         self.width = float(input('宽:'))

  8.     def getRect(self):
  9.         print('这个举行的长是:%.2f, 宽是:%.2f' % (self.length, self.width))

  10.     def getArea(self):
  11.         return self.length * self.width
复制代码


运行结果:
  1. >>> rect = Rectangle()
  2. >>> rect.getRect()
  3. 这个矩形的长是:5.00,宽是:4.00
  4. >>> rect.setRect()
  5. 请输入矩形的长和宽...
  6. 长:3.5
  7. 宽:5
  8. >>> rect.getRect()
  9. 这个矩形的长是:3.50,宽是:5.00
  10. >>> rect.getArea()
  11. 17.5
  12. >>> Rectangle().getRect()
  13. 这个矩形的长是:5.00,宽是:4.00
  14. >>> Rectangle().setRect()
  15. 请输入矩形的长和宽...
  16. 长:1
  17. 宽:2
  18. >>> Rectangle().getArea()
  19. 20
复制代码
最佳答案
2021-2-2 10:28:43
本帖最后由 sunrise085 于 2021-2-2 10:32 编辑

类属性也可以修改,但是你在运行结果中,从来没有修改过类属性,修改的一直都是实例化属性
你写的方法setRect方法,只修改了实例属性,没有修改类属性,因此类属性length和width一直没有变过。
修改类属性,需要使用类名称修改,如下:
Rectangle.length=2
可以看看我写过的这个总结,希望对你有帮助。
python细节之8、类属性(方法)和类实例化属性(方法)
小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

发表于 2021-2-2 10:19:05 | 显示全部楼层
因为你后来又重新实例化了一个Rectangle,而你没有给它设置长和宽的属性,
所以结果是20。

评分

参与人数 1荣誉 +5 鱼币 +5 收起 理由
°蓝鲤歌蓝 + 5 + 5 说的虽然不够仔细,但是说的没错

查看全部评分

小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 1 反对 0

使用道具 举报

发表于 2021-2-2 10:28:43 | 显示全部楼层    本楼为最佳答案   
本帖最后由 sunrise085 于 2021-2-2 10:32 编辑

类属性也可以修改,但是你在运行结果中,从来没有修改过类属性,修改的一直都是实例化属性
你写的方法setRect方法,只修改了实例属性,没有修改类属性,因此类属性length和width一直没有变过。
修改类属性,需要使用类名称修改,如下:
Rectangle.length=2
可以看看我写过的这个总结,希望对你有帮助。
python细节之8、类属性(方法)和类实例化属性(方法)
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2021-2-2 10:45:53 | 显示全部楼层
本帖最后由 °蓝鲤歌蓝 于 2021-2-2 11:43 编辑

应该是覆盖了。
这个问题很有意思,很久没遇到这么有意思的提问了。
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2021-2-2 11:39:12 | 显示全部楼层
sunrise085 发表于 2021-2-2 10:28
类属性也可以修改,但是你在运行结果中,从来没有修改过类属性,修改的一直都是实例化属性
你写的方法setR ...
  1. >>> rect = Rectangle()
  2. >>> rect.getRect()
  3. 这个矩形的长是:5.00,宽是:4.00
  4. >>> rect.setRect()
  5. 请输入矩形的长和宽...
  6. 长:3.5
  7. 宽:5
  8. >>> rect.getRect()
  9. 这个矩形的长是:3.50,宽是:5.00
  10. >>> rect.getArea()
  11. 17.5
复制代码


这一段也没有修改 类属性,可是实例的属性还是改变了的。
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2021-2-2 11:40:00 | 显示全部楼层
本帖最后由 °蓝鲤歌蓝 于 2021-2-2 12:01 编辑
qiuyouzhi 发表于 2021-2-2 10:19
因为你后来又重新实例化了一个Rectangle,而你没有给它设置长和宽的属性,
所以结果是20。

  1. Rectangle().getRect()
  2. 这个矩形的长是:5.00,宽是:4.00
  3. >>> Rectangle().setRect()
  4. 请输入矩形的长和宽...
  5. 长:1
  6. 宽:2
  7. >>> Rectangle().getArea()
  8. 20
复制代码


这一段的三个 Rectangle() 都是同一个对象。
补: 说的不够严谨,应该说它们的地址有时候是相同的
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2021-2-2 12:13:34 | 显示全部楼层
本帖最后由 °蓝鲤歌蓝 于 2021-2-2 12:14 编辑

二楼的才是正确答案,在这里补充一下。
  1. >>> Rectangle().getRect()
  2. 这个矩形的长是:5.00,宽是:4.00
  3. >>> Rectangle().setRect()
  4. 请输入矩形的长和宽...
  5. 长:1
  6. 宽:2
  7. >>> Rectangle().getArea()
  8. 20
复制代码

这三个 Rectangle() , 是不同的对象,但它们的地址有可能相同。我测试的时候在这里被误导了,还以为三个对象共用一个地址。
因为每个 Rectangle() 被用完后就回收掉了,也就是说运行完
  1. Rectangle().getRect()
复制代码
之后,第一个 Rectabgle() 就被回收了,此时它的地址也空出来了,所以第二个 Rectangle() 创建时仍然有可能使用该地址。
同理第二个、第三个都是被使用完就被回收了,所以三个 Rectangle() 分别是三个不同的 实例对象。
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2021-2-2 13:34:56 | 显示全部楼层
qiuyouzhi 发表于 2021-2-2 10:19
因为你后来又重新实例化了一个Rectangle,而你没有给它设置长和宽的属性,
所以结果是20。

谢谢!
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2021-2-2 13:39:47 | 显示全部楼层
°蓝鲤歌蓝 发表于 2021-2-2 12:13
二楼的才是正确答案,在这里补充一下。

这三个 Rectangle() , 是不同的对象,但它们的地址有可能相同。 ...

这么深奥啊?
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2021-2-2 13:44:19 | 显示全部楼层

这个哪里深奥了?
实例化对象你会吧? 那么这三个 Rectangle() 就相当于你分别实例化了三个对象 r1, r2, r3,
那么它们进行的操作( set/get ) 就互不影响,所以你提问里的那个 length 和 width 才会没改变。
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2021-2-2 13:55:04 | 显示全部楼层
本帖最后由 Peteryo01223 于 2021-2-2 14:07 编辑
°蓝鲤歌蓝 发表于 2021-2-2 13:44
这个哪里深奥了?
实例化对象你会吧? 那么这三个 Rectangle() 就相当于你分别实例化了三个对象 r1, r2, ...


好的,我又重新读了一遍,感觉明白了。感谢详细解释,受益匪浅!

以后,我再使用类的时候,为了保持一致,就先用 rect = Rectangle() 这种形式,再操作rect.getRect() 等等。比每次都直接调用 Rectangle() 保险,否则又会出现对象一次一变了。

我觉得有点儿像是:下载 windows, 然后买电脑。哈哈。如果,下载的windows,存在了一个硬盘里,每次装到电脑上再卖出去,就能保持一致。但,如果下载的 windows,每次都是临时去微软官网download,再把PC卖出去,很可能前后下载的的版本,已经被更新了,win7 win8 win9等等,这样,装在pc上再卖出去,这些电脑都不一样了,都是不同的对象。

我的例子中,临时赋值 1 和 2,等于是自己给 windows “改”了参数。但下面又直接从“官网”下载了一次windows,自然其中参数根本没变化。

小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2021-2-2 14:13:20 | 显示全部楼层
本帖最后由 °蓝鲤歌蓝 于 2021-2-2 14:14 编辑
Peteryo01223 发表于 2021-2-2 13:55
好的,我又重新读了一遍,感觉明白了。感谢详细解释,受益匪浅!

以后,我再使用类的时候,为了保持 ...


有空还是额外了解一下计算机基础吧。
举个例子:
  1. r = Rectangle()
复制代码

相当于你在一张纸上画了个 矩形,
  1. rect.getRect()
复制代码

然后,你获得了这个矩形的长宽
  1. rect.setRect()
复制代码

你修改了这个矩形的长宽
  1. rect.getArea()
复制代码

你求得了这个矩形的面积

注:上面的所有操作都是作用在 同一张纸上的同一个矩形 r 上的。

而下面这种
  1. Rectangle().getRect()
复制代码

你在纸上画了个矩形,并获得了它的长宽,然后把它涂掉了
  1. Rectangle().setRect()
复制代码

你又在纸上画了个矩形,并修改了它的长宽,然后又把它涂掉了
  1. Rectangle().getArea()
复制代码

你又又在纸上画了个矩形,并求得了它的面积,然后又又把它涂掉了

[b]注1:上面的操作都是作用在不同的 矩形 上的,它们都互不影响,所以虽然你在第二个矩形上修改了长宽,但是你又把它涂掉了(其实是python自己涂的,这里只是打个比方),所以第三个矩形的长宽根本没改变,就是那个默认的

注2:上面三个矩形可能是在同一张纸上,可能是不同的纸上(其实也不是你决定的,是python决定的),这个纸就相当于 内存地址

注3:规定这里的 纸 上只能画一个 矩形
[/b]

评分

参与人数 1荣誉 +5 鱼币 +5 贡献 +3 收起 理由
Peteryo01223 + 5 + 5 + 3 鱼C有你更精彩^_^

查看全部评分

小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 1 反对 0

使用道具 举报

 楼主| 发表于 2021-2-2 14:22:46 | 显示全部楼层
°蓝鲤歌蓝 发表于 2021-2-2 14:13
有空还是额外了解一下计算机基础吧。
举个例子:


好的,我思路更清晰了一些了。谢谢。
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

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

本版积分规则

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

GMT+8, 2025-4-26 07:38

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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