2015-05-27 66 views
-1

下面是简单的Python代码,Case 1和Case 2之间有什么区别,为什么我在第一种情况下得到的结果为False,在其他情况下为True。在案例2中为什么id是相等的?dir(object)在内部调用object._dir __()吗?如果是这样,两个调用的返回对象/结果应该是相同的。Python dir(object)vs 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

如果你不认为你的问题是重复的,请添加注释以解释原因。如果答案(无论是原始问题还是这个答案)都不涵盖你想知道的所有内容,请添加评论。只需重复编辑您的问题,并希望我们会注意到这些更改只有在您的时机非常幸运时才有效。 – abarnert

+0

@abarnert,我很新的stackoverflow。我会在下一次做,谢谢你让我知道。 – ravi

+0

没问题。我什么都没说,只是在我正要关闭页面时偶然注意到其中一个编辑,并通过编辑我的答案来回答它,并且我不想给出错误的印象,即您可以依靠每天的这种时机。 – abarnert

回答

1

这只是你曾经得到True巧合。 (嗯,不是一个巧合,因为CPython的实施使得它非常有可能...但它不是语言的要求。)

在案例1,您在var1var2有两个不同的dict秒。他们同时活着,所以他们不能有相同的id

在情况2中,您再次有两个不同的dict s--但是这一次,您没有将它们存储在任何地方;一旦你打电话给id,你就释放它,这意味着它可以在你得到另一个*之前得到垃圾回收,**这意味着它最终可以重复使用相同的id***

注意,为id文档说:

这是保证是用于在其寿命期间该对象独特和恒定的整数。具有非重叠寿命的两个对象可能具有相同的id()值。

如果你真的想测试两个表达式是否指向同一个对象,使用is,不比较他们的id秒。


你编辑的问题也问:

也做目录(对象)调用object._dir __()在内部?

根据dir

如果对象有一个名为__dir__()方法,这个方法将被调用,必须返回属性的列表。

而且在__dir__数据模型节说:

dir()被称为对象上调用。必须返回一个序列。 dir()将返回的序列转换为列表并对其进行排序。

然后你说:

如果是两个调用返回的对象应该是相同的。

那么,这取决于你是什么意思的“相同”。它应该返回等于的值(因为没有任何变化),但它不会是相同的值,这正是您要测试的值。 (如果不是显而易见的,为什么dir为您提供了一个新的列表中的每个时刻,它仍然应该清楚,它必须说:“dir()返回序列转换到一个列表并对其排序,”其实这样做......)


*由于CPython使用引用计数作为其主垃圾回收机制,“可以收集”通常意味着“将立即收集”。对于大多数其他Python实现,这不是真的。

**如果您阅读文档时不清楚表达式部分的顺序,那么您可以尝试dis.dis('id(dir(hello)) == id(hello.__dir__())')以按顺序查看实际的字节码。

***在CPython的,所述idPyObject结构表示对象的只是地址;如果一个PyObject被释放,并且另一个相同类型被立即分配,它通常会得到相同的地址。

+0

对dir(object)和object._dir __()具有相同的id使我感到困惑,现在很明显。谢谢。 另外如果dir(object)调用object .__ dir __(),为什么对__dir __()的调用没有出现在反汇编代码中? dis.dis('dir(hello)') – ravi