鱼C论坛

 找回密码
 立即注册
查看: 1263|回复: 9

[已解决]对39讲第0题的疑问,应该是没理解绑定

[复制链接]
发表于 2020-7-8 08:50:59 | 显示全部楼层 |阅读模式

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

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

x
对于零基础学习Python中第39讲第0题,我写的代码如下
class C:
    count = 0

    def __init__(self):
        C.count += 1
    def __del__(self):
        C.count -= 1
    def get_num(self):
        print('类实例个数是%d个' % C.count)
然后
c1 = C()
我是这样理解的:代码里面是C.count而不是self.count,其原因是如果用self.count,那么就变成对每个类实例的count属性进行赋值,而不是对C类进行操作。另外不明白为什么用c1.__dict__查看c1,c1为什么没有属性count,但是用c1.count明明又可以输出值? 还有一个就是为什么c1.get_num()是对的,而C.get_num()就说没有参数self,那要怎么样设置参数,才能够使用C.get_num()呢?谢谢
最佳答案
2020-7-8 09:02:25
本帖最后由 Twilight6 于 2020-7-8 09:11 编辑




先要分清楚类中的各种变量区分:
类体中、所有函数之外:此范围定义的变量,称为类属性或类变量;
类体中,所以函数内部:以“self.变量名”的方式定义的变量,称为实例属性或实例变量;
类体中,所有函数内部:以“变量名=变量值”的方式定义的变量,称为局部变量。
然后我们看看问题:

代码里面是C.count而不是self.count,其原因是如果用self.count,那么就变成对每个类实例的count属性进行赋值,而不是对C类进行操作。


count 参数在类内,方法外,属于类变量,而带 self 的变量在方法内属于实例对象,C.count 肯定不是self.count


另外不明白为什么用c1.__dict__查看c1,c1为什么没有属性count,但是用c1.count明明又可以输出值?


类变量是属于类本身的,而 __dict__ 属性是查看对象内部所有属性名和属性值组成的字典

你对 c1 使用属性 __dict__ 是查看这个实例对象所拥有的,所以你看不到 count 属性,你可以 C.__dict__ 来查看类对象所拥有的,就会发现字典中有 'count':'0' 了

还有记住一个对象的属性查找顺序遵循首先查找实例对象自己,然后是类,接着是类的父类。,当你在实例对象自动中找不到  count  属性,那么他就会去 类中找,类中这里找到了,所以返回了

如果你在类中还是没找到 count 属性,那么他就会去父类找 count 属性,直到找到输出,或者没找到导致报错


还有一个就是为什么c1.get_num()是对的,而C.get_num()就说没有参数self,那要怎么样设置参数,才能够使用C.get_num()呢?


self 实际上就是你的实例对象,而当你对类实例化后的对象调用 get_num() ,这里就会将 c1 这个实例对象自动传入 get_num(self) 中的  self,你如果想直接调用类的方法,你可以随便传入一个对象进去,只要是对象都行:
C.get_num(1)
C.get_num('')
C.get_num('asd')
C.get_num([])



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

使用道具 举报

发表于 2020-7-8 09:02:01 | 显示全部楼层
1、c1为什么没有属性count,但是用c1.count明明又可以输出值?

要明白为啥“c1为什么没有属性count,但是用c1.count明明又可以输出值?”,你首先得了解python类的机制:

类实例化后,是没有count这个属性的,但是可以查找到。这就说明实例化类属性没有的,会去上一级定义类中查找。所以count没有dict,但是有输出值。

但是,重点来了:假如你给c1的count赋值了之后,c1的count就会变成实例化类的私有属性,跟定义类中的count所在的栈不同了,这个时候你也就能查到c1中count的dict了。




2、那要怎么样设置参数,才能够使用C.get_num()呢?

不设置self参数,自然就可以调用C.get_num().

但是这就是个静态函数了,你设置在类外也是可以的,不太符合PEP-8的规范,不如将其设置为类方法。

一般情况下,你设置类,就是为了实例化类,所以这个self是必须有的。



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

使用道具 举报

发表于 2020-7-8 09:02:25 | 显示全部楼层    本楼为最佳答案   
本帖最后由 Twilight6 于 2020-7-8 09:11 编辑




先要分清楚类中的各种变量区分:
类体中、所有函数之外:此范围定义的变量,称为类属性或类变量;
类体中,所以函数内部:以“self.变量名”的方式定义的变量,称为实例属性或实例变量;
类体中,所有函数内部:以“变量名=变量值”的方式定义的变量,称为局部变量。
然后我们看看问题:

代码里面是C.count而不是self.count,其原因是如果用self.count,那么就变成对每个类实例的count属性进行赋值,而不是对C类进行操作。


count 参数在类内,方法外,属于类变量,而带 self 的变量在方法内属于实例对象,C.count 肯定不是self.count


另外不明白为什么用c1.__dict__查看c1,c1为什么没有属性count,但是用c1.count明明又可以输出值?


类变量是属于类本身的,而 __dict__ 属性是查看对象内部所有属性名和属性值组成的字典

你对 c1 使用属性 __dict__ 是查看这个实例对象所拥有的,所以你看不到 count 属性,你可以 C.__dict__ 来查看类对象所拥有的,就会发现字典中有 'count':'0' 了

还有记住一个对象的属性查找顺序遵循首先查找实例对象自己,然后是类,接着是类的父类。,当你在实例对象自动中找不到  count  属性,那么他就会去 类中找,类中这里找到了,所以返回了

如果你在类中还是没找到 count 属性,那么他就会去父类找 count 属性,直到找到输出,或者没找到导致报错


还有一个就是为什么c1.get_num()是对的,而C.get_num()就说没有参数self,那要怎么样设置参数,才能够使用C.get_num()呢?


self 实际上就是你的实例对象,而当你对类实例化后的对象调用 get_num() ,这里就会将 c1 这个实例对象自动传入 get_num(self) 中的  self,你如果想直接调用类的方法,你可以随便传入一个对象进去,只要是对象都行:
C.get_num(1)
C.get_num('')
C.get_num('asd')
C.get_num([])



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

使用道具 举报

发表于 2020-7-8 09:06:50 | 显示全部楼层
楼上说的对~~~
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2020-7-8 09:10:34 | 显示全部楼层
本帖最后由 热气球 于 2020-7-8 09:15 编辑

c1.__dict__没有count属性:因为类定义中用的都是类对象的count,而实例化对象自身却没有counut属性。c1.count能输出是因为访问了C.count即类对象的值。
C.get_num()之所以报错是因为没有实例化,只有实例化的实例对象才有self参数。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2020-7-8 09:17:54 | 显示全部楼层
Twilight6 发表于 2020-7-8 09:02
先要分清楚类中的各种变量区分:
然后我们看看问题:

大佬解释的就是清楚,受教了哈哈
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2020-7-8 09:19:11 | 显示全部楼层
热气球 发表于 2020-7-8 09:17
大佬解释的就是清楚,受教了哈哈

互相学习~
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 1 反对 0

使用道具 举报

 楼主| 发表于 2020-7-8 10:38:53 | 显示全部楼层
Twilight6 发表于 2020-7-8 09:02
先要分清楚类中的各种变量区分:
然后我们看看问题:

再问一下,如果改成
def get_num():
        print('类实例个数是%d个' % C.count)
也就是把self参数去掉,的确C.get_num()可以正确运行,但是c1.get_num()就出错。是不是说如果是像c1这样类实例对象调用get_num时,会把自己作为参数传入。而像C这样的类对象,因为get_num本身就是类方法,而其中没有参数,因此不会传入?谢谢
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2020-7-8 10:40:56 | 显示全部楼层
Tshirt 发表于 2020-7-8 10:38
再问一下,如果改成
def get_num():
        print('类实例个数是%d个' % C.count)

对的 实例化后 self 都是把自己传入了,没实例化前因为不知道 self 指的是水导致报错的
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2020-7-8 12:40:30 | 显示全部楼层
Twilight6 发表于 2020-7-8 10:40
对的 实例化后 self 都是把自己传入了,没实例化前因为不知道 self 指的是水导致报错的

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

使用道具 举报

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

本版积分规则

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

GMT+8, 2025-1-18 20:30

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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