【问题标题】:Checking objects reference equality in Python seems incoherent在 Python 中检查对象引用相等性似乎不连贯
【发布时间】:2018-09-24 13:23:20
【问题描述】:

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

我无法理解 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] id4378999048,但再次打印它会得到另一个 id (4378998328 >)
  2. 第三次打印也是如此;看起来第一行打印的 id 丢失/更改/未使用。
  3. 第一个 "Test with self" 打印有意义(id 字符串的比较为 True);但我无法理解第二次打印的感觉,使用is(为什么是sel[0] is not sel[0]?)。

我试图了解这里的东西是如何工作的。具体来说,目的是了解为什么我在使用带有for 的生成器表达式时会得到新对象(而不是对同一对象有新的引用)。

我使用 SublimeText3Python 2.7.10

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

【问题讨论】:

  • 没有不一致。这两个对象是同一个对象,或者不是。 is 会检查它。您不应该做的是依赖于两个指向具有相同值的对象的不可变对象的引用作为同一个对象。由于 Python 内部优化,它可以相同也可以不同,因为这无关紧要(您无法更改它们)。
  • @progmatico with "依赖于两个指向具有相同值的对象的不可变对象的引用,成为同一个对象" 你指的是== 比较吗?在这种情况下,我知道身份只是在值中(这实际上是我最初的问题;我需要确保对象相同,而不是另一个具有相同值的对象)。我还是不明白为什么sel[0] is sel[0] 返回False
  • 出于好奇,这个问题是否是您在 Sublime 插件中尝试做的某事未按您预期的方式工作的结果?
  • 是:获取选择范围,基于它们处理视图,根据视图变化保持选择更新。 View 的(唯一)Selection 有多个 Range*(s); *Range 的缓冲区指针根据父 View 上执行的操作进行更新。但是,根据我的推断(不知道 Sublime 内部结构),将 view.sel() 项目放入列表中会使它们脱离上下文(创建新的 Range 对象,而不是将这些对象引用到 View 选择因此我在上面使用is 进行了测试);如果 view.replace() 使用这些分离的区域,则 ViewSelection 将不会更新。

标签: python sublime-text-plugin


【解决方案1】:

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

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

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

【讨论】:

    【解决方案2】:

    看这个例子:

    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
    

    【讨论】:

      猜你喜欢
      • 2012-05-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-06-23
      • 1970-01-01
      • 2019-06-26
      • 1970-01-01
      相关资源
      最近更新 更多