鱼C论坛

 找回密码
 立即注册
查看: 678|回复: 7

关于类和实例的问题

[复制链接]
发表于 2019-2-21 23:00:36 | 显示全部楼层 |阅读模式

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

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

x
先列举一个代码:
class C:
        count = 0
        def __init__(self):
                C.count = C.count +1
这个代码实现的功能就是每创造一个实例对象,就会记录一次,看到这里,我突然就产生几个问题疑惑

问题1:
a=C(),运行后得到结果C.count=1;实例拥有类的属性和方法,那么我再用b=a,为什么C.count还是等于1,__init__方法没有被成功调用?

问题2:
基于问题1,我上网查了资源,有这么一个猜想,__init__方法是需要类创建实例才会被调用,由于b=a,不属于类创建实例,所以没有成功调用;那么b=a属于一个怎样的过程操作?

问题3:
看到这个问题,自然就想起了之前闭包的知识,有没有办法实现在不修改类的初始值的前提下,实现每创造一个实例对象,就会记录一次的功能?

以上的问题属于基础问题,本人查了很多资料,有一定想法,但总感觉不踏实,希望得到各位大大的解答,谢谢
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2019-2-21 23:28:49 | 显示全部楼层
本帖最后由 °蓝鲤歌蓝 于 2019-2-21 23:31 编辑

1. 不是没成功调用,而是根本就没调用。
2. 你的想法是正确的, b=a时并不会创建一个新的实例。
a = C()时创建一个实例对象,这时会分配一个内存空间用来存储这个实例,这块内存空间有自己的地址(查看对象地址使用 id(a)),a = C() 表明 a 指向存储该实例的内存空间,b=a 则表示 b也指向该内存空间,如果是创建了一个新的实例,则 b 会指向一个新的内存空间。
你可以输入
  1. print(a is b)
复制代码

(is 用来判断地址是否相同,== 则是判断值是否相同)
3. 类的初始值是什么意思?
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2019-2-22 00:04:16 | 显示全部楼层
本帖最后由 Stubborn 于 2019-2-22 00:07 编辑

只能再初始化的时候记录,不在初始化记录没法子
  1. class C:
  2.     count = 0

  3.     def __init__(self):
  4.         print("正在调用")
  5.         self.prin()

  6.     def prin(self):
  7.         self.count = self.count + 1
  8.         print("测试=",self.count)

  9. a = C()
  10. b = a
  11. print("a的类型={}.内存id={},值{}".format(type(a),id(a),a))
  12. print("a的类型={}.内存id={},值{}".format(type(b),id(b),b))
  13. print("a对象测试:",a.prin())
  14. print("b对象测试:",b.prin())

  15. aa = 2
  16. bb = aa
  17. print("aa的类型={}.内存id={},值{}".format(type(aa),id(aa),aa))
  18. print("a的类型={}.内存id={},值{}".format(type(bb),id(bb),bb))
复制代码

结果
  1. 正在调用
  2. 测试= 1 #初始化类调用函数一次,下面都是调用函数才发生的次数
  3. a的类型=<class '__main__.C'>.内存id=44007320,值<__main__.C object at 0x00000000029F7F98>
  4. a的类型=<class '__main__.C'>.内存id=44007320,值<__main__.C object at 0x00000000029F7F98>
  5. 测试= 2
  6. a对象测试: None
  7. 测试= 3
  8. b对象测试: None
  9. aa的类型=<class 'int'>.内存id=8791298004032,值2
  10. a的类型=<class 'int'>.内存id=8791298004032,值2
复制代码
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2019-2-22 00:24:48 | 显示全部楼层
°蓝鲤歌蓝 发表于 2019-2-21 23:28
1. 不是没成功调用,而是根本就没调用。
2. 你的想法是正确的, b=a时并不会创建一个新的实例。
a = C() ...

感谢大大的回答 初始值就是指 让C.count=0  而不是经过几次调用后,count就不等于0了
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2019-2-22 00:38:36 | 显示全部楼层
°蓝鲤歌蓝 发表于 2019-2-21 23:28
1. 不是没成功调用,而是根本就没调用。
2. 你的想法是正确的, b=a时并不会创建一个新的实例。
a = C() ...

再追问大大一个问题
为什么a.count()的结果会随着C.count的变化而变化,但是在del C 后依然能使用a.count()
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2019-2-22 12:43:01 | 显示全部楼层
1.2. b=a, 是b引用a的值,即b引用了实例a,并不产生新的类实例化对象。
3. 常用的闭包函数-->以装饰器实现count实例:
  1. # decorator
  2. def count_info(func):
  3.     count_info.count = 0
  4.     def inner(*args, **kwargs):
  5.         count_info.count += 1
  6.         return func(*args, **kwargs)
  7.     return inner

  8. @count_info
  9. class Myclass:
  10.     pass

  11. mc1 = Myclass()
  12. mc2 = Myclass()
  13. print(count_info.count)  # 2

  14. # 或者利用类方法实现count实例
  15. class Stone:
  16.     count = 0
  17.     def __init__(self):
  18.         type(self).count += 1

  19.     @classmethod
  20.     def count_info(cls):
  21.         return cls.count

  22. stone1 = Stone()
  23. stone2 = Stone()
  24. stone3 = Stone()
  25. print(Stone.count_info()) # 3
复制代码

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

使用道具 举报

 楼主| 发表于 2019-2-22 13:44:32 | 显示全部楼层
stonejianbu 发表于 2019-2-22 12:43
1.2. b=a, 是b引用a的值,即b引用了实例a,并不产生新的类实例化对象。
3. 常用的闭包函数-->以装饰器实现 ...

嗯嗯,这三个问题已经明白了
现在还有这个问题
为什么a.count的结果会随着C.count的变化而变化,但是在del C 后依然能使用a.count
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2019-2-23 19:46:25 | 显示全部楼层
qq511383041 发表于 2019-2-22 13:44
嗯嗯,这三个问题已经明白了
现在还有这个问题
为什么a.count的结果会随着C.count的变化而变化,但是在 ...
  1. class Foo:
  2.     count = 1

  3. f = Foo()
  4. # del Foo
  5. print(f.count) # 1
  6. print(f.__class__, f.__class__.__dict__['count']) # <class '__main__.Foo'> 1
  7. # print(Foo)  # name 'Foo' is not defined, 类和实例都是独立的命名空间,删除类并不影响由其已创建的实例
  8. print(Foo.__mro__) # 父类元组,左至右开始查找顺序

  9. # 在未设置__slots__时,一般的查找顺序instance.__dict__==> __class__.__dict__===>___bases__.__dict__(广度优先)
复制代码
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

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

本版积分规则

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

GMT+8, 2024-4-26 09:31

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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