我很好奇为什么用is
替换==
会导致.py
在直接启动时失败。
if __name__ == '__main__':
main()
和
if __name__ is '__main__':
main()
对象标识在这里是如何工作的?
我特别好奇__name__
和__main__
具有不同身份的机制和目的。
is
表示两者是同一对象(即它们具有相同的id
)。显然,__name__
是一个不同于'__main__'
的字符串(即使它们有相同的文本)。
一般来说,只有当你真正的意思是"检查这些是完全相同的对象"时才使用is
——永远不要用它来表示"这些对象是相等的"。
下面的几个例子会让它更明显:
In [7]: foo = 1000
In [8]: bar = 1000
In [9]: foo is bar # same value but different objects so identity test is False
Out[9]: False
In [10]: foo == bar # equality test is True
Out[10]: True
In [11]: id(foo) # both have different id's
Out[11]: 41007616
In [12]: id(bar)
Out[12]: 40841432
In [13]: foo = bar # now make foo point to the object bar
In [14]: foo is bar # now foo is bar so identity check is True
Out[14]: True
In [15]: id(bar) # matching id's
Out[15]: 40841432
In [16]: id(foo)
Out[16]: 40841432
要比较值,使用==
检查身份,使用is
需要注意的是,小整数-5
到256
和字符串在python中被缓存和重用,所以如果你分配a = 10
和b = 10
,它们实际上都指向同一个对象,所以a is b
。
In [20]: a = 256
In [21]: b = 256
In [22]: a is b
Out[22]: True
In [23]: a = 257
In [24]: b = 257
In [25]: a is b
Out[25]: False
In [26]: foo = "foo"
In [27]: bar = "foo"
In [28]: foo is bar
Out[28]: True
In [29]: foo = "$bar"
In [30]: bar = "$bar"
In [31]: foo is bar # now False because it does not start with an _ or a letter
Out[31]: False
字符串只有在以underscore
或letter
开头并且只包含letters
, numbers
或underscores
时才会被缓存:
__main__
失败的最后一个例子:
# first __main__ object inside locals dict, second is just a string __main__
print id(locals()['__name__']),id("__main__")
print (locals()['__name__']) is "__main__" # so not the same object
print (locals()['__name__']) == "__main__" # but == strings
if __name__ == "__main__":
print id(locals()['__name__']), id(__name__ ) # same id's
print (locals()['__name__']) is __name__ ) # same object stored in locals
140168071262544 140168071262592
False
True
140168071262544 140168071262544
True