以下是简单的Python代码:案例1和案例2之间有什么区别 - 为什么我在第一种情况下将结果视为False而在其他情况下获得True?案例2中为什么id
s相等? dir(object)
内部也会调用object._dir__()
吗?如果是这样,两个调用的返回对象/结果应该是相同的。
class Hello:
def __init__(self):
self.a1 = "a1"
hello = Hello()
print(hello)
# Case 1
var1 = dir(hello)
var2 = hello.__dir__()
print(id(var1), id(var2), id(var1) == id(var2))
# Case 2
print(id(dir(hello)), id(hello.__dir__()), id(dir(hello)) == id(hello.__dir__()))
print(dir(hello) == hello.__dir__())
输出
<__main__.Hello object at 0x7f320828c320>
139852862206472 139852862013960 False
139852862014024 139852862014024 True
False
答案 0 :(得分:2)
你得到True
只是巧合。 (好吧,不是巧合,因为CPython的实现很可能......但这不是语言所需要的。)
在案例1中,您在dict
和var1
中有两个不同的var2
。他们同时还活着,所以他们不能拥有相同的id
。
在案例2中,您再次有两个不同的dict
s - 但这一次,您没有将它们存储在任何地方;一旦你在一个上面调用id
,你就会释放它,这意味着它可以在你获得另一个之前收集垃圾 * , ** 这意味着它最终可能会重复使用相同的id
。 ***
请注意id
的文档说:
这是一个整数,在该生命周期内,该对象保证唯一且恒定。具有非重叠生存期的两个对象可能具有相同的
id()
值。
如果您确实想测试两个表达式是否引用同一个对象,请使用is
,不要比较它们的id
。
您编辑过的问题也会问:
dir(object)也在内部调用object._dir __()吗?
根据dir
:
如果对象具有名为
__dir__()
的方法,则将调用此方法,并且必须返回属性列表。
__dir__
上的数据模型部分说:
在对象上调用
dir()
时调用。必须返回一个序列。dir()
将返回的序列转换为列表并对其进行排序。
然后你说:
如果是这样,两个调用的返回对象应该是相同的。
嗯,这取决于你所说的“相同”。它应该返回一个相等的值(因为没有任何变化),但它不会是相同的值,这是你要测试的值。 (如果为什么dir
每次为您提供一个新列表并不明显,那么必须必须这样做是因为“dir()
转换了将序列返回到列表并对其进行排序“...)
*因为CPython使用引用计数作为其主要垃圾收集机制,“可以收集”通常意味着“将立即收集”。对于大多数其他Python实现,情况并非如此。
**如果您在阅读文档时不清楚表达部分的评估顺序,您可以尝试dis.dis('id(dir(hello)) == id(hello.__dir__())')
按顺序查看实际的字节码。
***在CPython中,id
只是表示对象的PyObject
结构的地址;如果一个PyObject
被释放,另一个同一类型被立即分配,它通常会获得相同的地址。