在Python中检查对象引用是否相等似乎不一致

时间:2018-09-24 13:23:21

标签: python sublime-text-plugin

我试图了解分配和对对象的新引用的创建会发生什么,或者为什么分配时会得到一个新创建的对象。

我无法理解 Python 和/或 Sublime 在这里的工作方式。 我有这个简单的 Sublime 插件:

import sublime
import sublime_plugin

class TestpythonCommand(sublime_plugin.TextCommand):
    def run(self, edit):
        view = self.view
        sel = view.sel()
        sel_zero = sel[0];
        sel_for = []
        for r in sel:
            sel_for.append(r)
        sel_gen = [r for r in view.sel()]

        print('SEL => ' + str(sel[0].a) +':' + str(sel[0].b) + ' ID: ' + str(id(sel[0])))
        print(str(id(sel[0])) + ' .. ' + str(id(sel[0])) + ' .. access A value: ' + str(sel[0].a) + ' .. ' + str(id(sel[0])))
        print('SEL[0] id is ' + str(id(sel[0])))
        print('SEL_ZERO => ' + str(sel_zero.a) +':' + str(sel_zero.b) + ' ID: ' + str(id(sel_zero)))
        print('SEL_FOR => ' + str(sel_for[0].a) +':' + str(sel_for[0].b) + ' ID: ' + str(id(sel_for[0])))
        print('SEL_GEN => ' + str(sel_gen[0].a) +':' + str(sel_gen[0].b) + ' ID: ' + str(id(sel_gen[0])))
        print('----- Test with self')
        print(id(sel[0]) == id(sel[0]))
        print(sel[0] is sel[0])
        print(sel[0] == sel[0])
        print('----- Test with list & generator function')
        print(sel[0] is sel_zero)
        print(sel[0] == sel_zero)
        print(sel[0] is sel_for[0])
        print(sel[0] == sel_for[0])
        print(sel[0] is sel_gen[0])
        print(sel[0] == sel_gen[0])

执行此操作将返回:

SEL => 657:657 ID: 4378999048
4378998328 .. 4378998328 .. access A value: 657 .. 4378998328
SEL[0] id is 4378998328
SEL_ZERO => 657:657 ID: 4379000488
SEL_FOR => 657:657 ID: 4378996816
SEL_GEN => 657:657 ID: 4378998760
----- Test with self
True
False
True
----- Test with list & generator function
False
True
False
True
False
True

现在,太多的事情对我来说毫无意义:

  1. 第一张印刷品显示sel[0] id 4378999048 ,但再次印刷将得到另一个 id 4378998328 < / strong>)
  2. 第三种印刷品也是如此;看起来第一行中打印的 id 丢失/更改/未使用。
  3. 第一个“自我测试” 打印很有意义(id字符串的比较为True);但是我无法使用is(为什么要sel[0] is not sel[0]?)来了解第二张纸。

我试图了解这里的工作原理。具体来说,目的是要理解为什么将Generator-expression与for一起使用时为什么会得到新的对象(而不是对同一对象有新的引用)。

我使用 SublimeText3 Python 2.7.10

编辑:我会对检查引用相等性的最佳实践感兴趣,而无需使用is(即seems to be inconsistent, depending on implementation and caching)。 / p>

2 个答案:

答案 0 :(得分:1)

在多个时间点打印表达式的id()证明是绝对没有的。如果不再引用第一个对象,则第二个对象可能分配在相同的地址,因此具有相同的id;在某些情况下,这实际上是相当可能的结果。两个对象必须同时存在 ,才能对其id进行有意义的比较。例如,

a = sel[0]
b = sel[0]
print(id(a), id(b))

对于sel的索引操作是每次返回同一对象还是从头开始创建一个对象,将是一个有效的测试。

答案 1 :(得分:0)

看这个例子:

from collections import UserList

class MyList(UserList):

    def __init__(self):
        self.gen = iter([10,20,30])

    def __getitem__(self, index):
        return next(self.gen)

# This is what you expect:
a = [10,20,30]
print(a[0] is a[0]) # True

# And this looks surprising at first:
b = MyList()
print(b[0] is b[0]) # False

# Without knowing MyList internals, I
# cannot predict what I am getting on
# each access (except maybe by trusting
# available documentation)

# I don't know about sublime.
# In my other comment I just wanted
# to emphasize that operator `is`
# works reliably.

# You don't know if a is b or not:
a = 1
b = 1
# a is b can be True or False.
# But as they hold the same immutable value
# it really doesn't matter. Things will work
# the same with either a or b.

# to find out about identity, just test with 
# a is b