鱼C论坛

 找回密码
 立即注册
查看: 1219|回复: 6

[已解决]这段代码问题出在哪里啊?课后习题42讲

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

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

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

x
  1. class Foo:
  2.         def foo(self):
  3.                 self.foo = "I love FishC.com!"
  4.                 return self.foo

  5. >>> foo = Foo()
  6. >>> foo.foo()
  7. 'I love FishC.com!'
复制代码


是不是实例对象调用一次foo方法,其实例对象属性中就由{‘foo’:'I love FishC.com!'}同名属性会覆盖方法,方法就失效了,调用foo.foo这一属性才会显示'I love FishC.com!',我的解释对吗?
最佳答案
2020-7-5 20:46:43
本帖最后由 Twilight6 于 2020-7-5 20:50 编辑




是不是实例对象调用一次foo方法,其实例对象属性中就由{‘foo’:'I love FishC.com!'}同名属性会覆盖方法,方法就失效了,调用foo.foo这一属性才会显示'I love FishC.com!',我的解释对吗?


是的,因为你当调用类中的 foo 方法时候 会设置属性 foo 的值导致覆盖了方法 foo() 最后导致你下次再次调用就会报错

因为此时这个实例对象你调用一次了 foo 之后,foo 就从方法变成了 实例属性,被实例属性所覆盖,你试着这样运行就会报错:

  1. class Foo:
  2.     def foo(self):
  3.         self.foo = "I love FishC.com!"
  4.         return self.foo

  5. foo = Foo()
复制代码


我们用 __dict__ 属性来查看对象内部所有属性名和属性值组成的字典
首先:
  1. >>> print(foo.__dict__)    # 第一次实例化打印属性,发现没有
  2. {}
复制代码

然后:
  1. >>> print(foo.foo())  # 成功调用,并且打印返回值
  2. I love FishC.com!
复制代码

继续:
  1. >>> print(foo.__dict__)    # 因为调用了 foo() 方法,所以此时设置了一个属性 foo
  2. {'foo': 'I love FishC.com!'}
复制代码

最后:
  1. >>> print(foo.foo())  # 成功报错
  2. Traceback (most recent call last):
  3.   File "M:/Python data/My Project/Work.py", line 10, in <module>
  4.     print(foo.foo())
  5. TypeError: 'str' object is not callable  # 字符串不可调用,因为此时的 foo 是个属性,而且值属于字符串,之前的 foo()方法已经被覆盖了
复制代码




想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2020-7-5 20:29:58 | 显示全部楼层
没明白你表达的什么意思。。。

追究到底层,类创建的时候默认一个空间,每实例化一个,实例化就拥有自己的独立空间。

所以foo1、foo2、foo3等实例化出来的类对象,空间都是独特的,每个实例化对象下面都有个foo方法,虽然名字一样,但是所属空间并不相同,你可以把实例化后的对象想象为函数不同的局部变量。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2020-7-5 20:46:43 | 显示全部楼层    本楼为最佳答案   
本帖最后由 Twilight6 于 2020-7-5 20:50 编辑




是不是实例对象调用一次foo方法,其实例对象属性中就由{‘foo’:'I love FishC.com!'}同名属性会覆盖方法,方法就失效了,调用foo.foo这一属性才会显示'I love FishC.com!',我的解释对吗?


是的,因为你当调用类中的 foo 方法时候 会设置属性 foo 的值导致覆盖了方法 foo() 最后导致你下次再次调用就会报错

因为此时这个实例对象你调用一次了 foo 之后,foo 就从方法变成了 实例属性,被实例属性所覆盖,你试着这样运行就会报错:

  1. class Foo:
  2.     def foo(self):
  3.         self.foo = "I love FishC.com!"
  4.         return self.foo

  5. foo = Foo()
复制代码


我们用 __dict__ 属性来查看对象内部所有属性名和属性值组成的字典
首先:
  1. >>> print(foo.__dict__)    # 第一次实例化打印属性,发现没有
  2. {}
复制代码

然后:
  1. >>> print(foo.foo())  # 成功调用,并且打印返回值
  2. I love FishC.com!
复制代码

继续:
  1. >>> print(foo.__dict__)    # 因为调用了 foo() 方法,所以此时设置了一个属性 foo
  2. {'foo': 'I love FishC.com!'}
复制代码

最后:
  1. >>> print(foo.foo())  # 成功报错
  2. Traceback (most recent call last):
  3.   File "M:/Python data/My Project/Work.py", line 10, in <module>
  4.     print(foo.foo())
  5. TypeError: 'str' object is not callable  # 字符串不可调用,因为此时的 foo 是个属性,而且值属于字符串,之前的 foo()方法已经被覆盖了
复制代码




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

使用道具 举报

发表于 2020-7-5 20:52:30 | 显示全部楼层
本帖最后由 永恒的蓝色梦想 于 2020-7-5 20:53 编辑

说的没错。理解很到位。
如果还需要使用这个函数的话,可以
  1. Foo.foo(foo)
复制代码
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2020-7-5 21:39:30 | 显示全部楼层
永恒的蓝色梦想 发表于 2020-7-5 20:52
说的没错。理解很到位。
如果还需要使用这个函数的话,可以

这是为啥啊,是调用类对象的方法吗,里边的参数是实例对象self,是这样吗?
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2020-7-5 21:45:24 | 显示全部楼层
lingedu 发表于 2020-7-5 21:39
这是为啥啊,是调用类对象的方法吗,里边的参数是实例对象self,是这样吗?

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

使用道具 举报

 楼主| 发表于 2020-7-5 21:46:05 | 显示全部楼层
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

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

本版积分规则

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

GMT+8, 2024-3-29 10:06

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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