关于类方法的知识求解
class Pizza(object):radius = 42
@classmethod
def get_radius(cls):
return cls.radius
print(id(Pizza.get_radius))
print(id(Pizza().get_radius))
Pizza.get_radius is Pizza().get_radius
结果:
2593923753792
2593923753792
>>> Pizza.get_radius is Pizza().get_radius
False
为啥对类和实例对象调用同一方法id相同,但是用is判断却是false?好疑惑求解 ???我编译器有假????? qiuyouzhi 发表于 2020-7-8 18:41
??
我这里是True?
我这里是 False。>>> class Pizza(object):
radius = 42
@classmethod
def get_radius(cls):
return cls.radius
>>> print(id(Pizza.get_radius));print(id(Pizza().get_radius));Pizza.get_radius is Pizza().get_radius
3036946592960
3036946592960
False
>>> (id(Pizza().get_radius))
3036950777920
>>> (id(Pizza.get_radius))
3036950769536 qiuyouzhi 发表于 2020-7-8 18:41
??
我这里是True?
我也是 False哈哈 qiuyouzhi 发表于 2020-7-8 18:41
??
我这里是True?
C:\Users\Administrator\Desktop/无标题.jpeg 本帖最后由 qiuyouzhi 于 2020-7-8 18:46 编辑
永恒的蓝色梦想 发表于 2020-7-8 18:43
我这里是 False。
噢,是我的问题
没事了,我说的是错的 lingedu 发表于 2020-7-8 18:44
用图床
https://imgchr.com 那为啥是false啊?不管调用类方法,类方法的存储地址不变啊,is判断不应该是true吗 lingedu 发表于 2020-7-8 18:48
那为啥是false啊?不管调用类方法,类方法的存储地址不变啊,is判断不应该是true吗
https://ask.csdn.net/questions/814466?sort=id
看这里 百度到了 :is只能用于比较Number、String、List、Tuple、Set、Dictionary六种以及定义为class的对象。 Twilight6 发表于 2020-7-8 18:53
https://ask.csdn.net/questions/814466?sort=id
看这里 百度到了 :is只能用于比较Number、String ...
我觉得这个解释不太正确。 永恒的蓝色梦想 发表于 2020-7-8 18:59
我觉得这个解释不太正确。
确实唉 https://fishc.com.cn/thread-49126-1-2.html
我是看这篇帖子发现的问题,我真的后边都看不懂了,类方法用类对象和实例对象都能调用,为啥他俩的地址会一样啊?我感觉不一样啊,正常的实例方法两个实例对象调用的id肯定不一样啊,结果用is一看是false,看id就是一样的,蒙了? Twilight6 发表于 2020-7-8 19:05
确实唉
哥,看完了,没明白啊,他也没说为啥地址会一样啊,而且我感觉他解释的不太对啊
is 关键字用于测试两个变量是否引用同一对象。
如果两个对象是同一对象,则 test 返回 True。
如果两个对象不是同一对象,即使两个对象 100% 相等,test 也会返回 False。
查了下应该是这样的,你单独的 Pizza 代表这个类本身,但是你加上 Pizza() 括号之后就和原来的 Pizza 不是一个对象了
所以这里是两个对象里面的同个方法,但是对象不同所以返回的是 False?
class Pizza(object):
radius = 42
@classmethod
def get_radius(cls):
return cls.radius
print(type(Pizza),id(Pizza.get_radius))
print(type(Pizza()),id(Pizza().get_radius))
输出结果:
<class 'type'> 1702059745152
<class '__main__.Pizza'> 1702059745152
以上我也不懂正确与否......这个问题确实有点意思
Twilight6 发表于 2020-7-8 19:13
查了下应该是这样的,你单独的 Pizza 代表这个类本身,但是你加上 Pizza() 括号之后就和原来的 Piz ...
对的Pizza是类对象吧,Pizza()是实例对象,他俩id肯定不同,都调用类方法,id相同,那为啥用id一查就不同了呢?我感觉你前面给我解释明白了,但是后边我就懵了 lingedu 发表于 2020-7-8 19:17
对的Pizza是类对象吧,Pizza()是实例对象,他俩id肯定不同,都调用类方法,id相同,那为啥用id一查就不 ...
都调用类方法,id相同,那为啥用id一查就不同了呢?
id 相同呀 容我再想想{:10_285:}晚上应该能给你答案 Twilight6 发表于 2020-7-8 19:28
id 相同呀
就是用is判断就不同,我感觉is也是比对id吧?? 本帖最后由 Twilight6 于 2020-7-8 20:42 编辑
又去查了一堆资料,终于有一点眉目了,看看Python官方文档怎么说 id() 函数的:
Return the “identity” of an object. This is an integer (or long integer) which is guaranteed to be unique and constant for this object during its lifetime.
Two objects with non-overlapping lifetimes may have the same id() value.
翻译成中文:返回对象的“标识”。这是一个整型数(或长整型数),保证该对象在其生命周期内是惟一的和常量。
具有不重叠生存期的两个对象可能具有相同的id()值。
而你对 Pizza.get_radius is Pizza().get_radius 进行比较时候,在内存产生个对象,然后销毁
然后再次产生个对象,然后再次销毁,而这两个对象 id 是有可能相等的,具体为什么就看上面官方文档的解释,但是实际上是两个对象,而不是同一个了
而因为 is 运算符检查两个运算对象是否引用自同一对象 (即, 它检查两个运算对象是否相同) 所以此时是两个不同对象,只是前后占用的系统内存相同
导致我们人为认为他们是一个id 实际上只是创建 id 的相同导致的巧合
你可以试着运行下面的代码:
class Pizza(object):
radius = 42
@classmethod
def get_radius(cls):
return cls.radius
print(id(Pizza.get_radius))
print(id(Pizza().get_radius))
print('-'*30)
a = Pizza.get_radius
b = Pizza().get_radius
print(id(a))
print(id(b))
运行结果:
2798669569920
2798669569920
------------------------------
2798669569920
2798669611072
会发现前面两个 id 相同,后面两个仅仅是给这两个变量取了个别名, id 就不同了
是因为这个代码和你的代码只有一个差别,就是楼主你的代码对象一产生就会被销毁,导致第二次产生的 id 相同
而这里的用一个变量指名后就被保留在内存之中,不会被销毁,所以本身就是不同对象,产生的 id 自然不同
这里会发现三个 id 都相同就是因为文档里面那句话的:为保证该对象在其生命周期内是惟一的和常量。具有不重叠生存期的两个对象可能具有相同的id()值。
我找了快一个半小时的资料,总算功夫不负有心人{:7_112:} !!!
本帖最后由 Stubborn 于 2020-7-8 21:25 编辑
is也被叫做同一性运算符,这个运算符比较判断的是对象间的唯一身份标识,也就是id是否相同。
最重要的一点,classmethod装饰器的调用等同于Object().method()
其过程可以看做这样
# 这里是两次打印ID
print(id(Pizza.get_radius))
print(id(Pizza.get_radius))
# 这里是使用 is 判断
a = Pizza()
b = Pizza()
print(a.get_radius is b.get_radius)
Pizza().get_radius Pizza.get_radius括号加不加都一样(Ps:调用方法都是一样,但是对象不是一样的,为什么ID会相同呢,在Python里面,未命名的相同类型的Python对象具有相同的ID,刚刚看到的),Pizza().get_radius is Pizza().get_radius这个为什么是False就很容易看出来了吧
class Pizza(object):
radius = 42
@classmethod
def get_radius(cls):
return cls.radius
def test(self): pass
print(id(Pizza().test))
print(id(Pizza.test))
aa = Pizza.test
bb = Pizza.test
print(id(aa))
print(aa is bb)
print(aa is Pizza.test)
print("装饰器方法")
print(id(Pizza.get_radius))
print(id(Pizza().get_radius))
a = Pizza.get_radius
print(id(a))
# 以上三个ID是完全一样,正常来说,使用is盘判断,肯定是True。
# 但是出现False 说明是重新申请的内存,就像这样
# b = Pizza.get_radius
# 赋值等同于ID传递引用。
print(a is Pizza.get_radius)
print(a is Pizza().get_radius)
b = Pizza.get_radius
print(id(b))
页:
[1]
2