dir(object)vs object .__ dir __()

时间:2015-05-27 03:36:47

标签: python class

以下是简单的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

1 个答案:

答案 0 :(得分:2)

你得到True只是巧合。 (好吧,不是巧合,因为CPython的实现很可能......但这不是语言所需要的。)

在案例1中,您在dictvar1中有两个不同的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被释放,另一个同一类型被立即分配,它通常会获得相同的地址。