【问题标题】:Python: default comparisonPython:默认比较
【发布时间】:2011-06-06 13:31:25
【问题描述】:

在 Python 2.7 中,我定义了一个空的新式类:

In [43]: class C(object): pass
   ....:

然后创建一个新类的实例列表:

In [44]: c = [C() for i in xrange(10)]

然后尝试对列表进行排序:

In [45]: sorted(c)
Out[45]:
[<__main__.C object at 0x1950a490>,
 <__main__.C object at 0x1950a4d0>,
 ...
 <__main__.C object at 0x1950aad0>]

令人惊讶的是,排序没有抱怨,即使我还没有定义一种方法来比较 C 的实例:

In [46]: dir(C())
Out[46]:
['__class__',
 '__delattr__',
 '__dict__',
 '__doc__',
 '__format__',
 '__getattribute__',
 '__hash__',
 '__init__',
 '__module__',
 '__new__',
 '__reduce__',
 '__reduce_ex__',
 '__repr__',
 '__setattr__',
 '__sizeof__',
 '__str__',
 '__subclasshook__',
 '__weakref__']

那里到底发生了什么,这种行为的基本原理是什么——可以说是令人惊讶的——行为?

【问题讨论】:

    标签: python object comparison


    【解决方案1】:

    我认为唯一的理由是可以方便地对对象进行排序,例如用作具有某些默认行为的字典键。语言定义的相关章节在这里:https://docs.python.org/2/reference/expressions.html#not-in

    “在程序的一次执行中,一个对象被认为比另一个对象更小还是更大的选择是任意的,但始终如一。”

    因此,当前使用内存地址比较对象的事实只是一个无法指望的实现细节。唯一的保证是在执行过程中顺序保持一致。

    【讨论】:

    • (+1) 链接和报价。
    • +1,你的评论完全正确,我被两个对象和其他比较运算符的相等性误导了,谢谢你找出我的错误
    【解决方案2】:

    我不太确定,但也许有人可以纠正我。

    当你比较对象时,它会比较它们的内存地址,想想在 C 中比较 2 个 cstrings。如果你看一下,排序将对象从最低内存地址排序到最高内存地址(或指针位置)。

    【讨论】:

    • 确实如此,但这似乎有点武断,因此相当不符合 Python 风格?
    • 嗯,在底层C代码中,当你比较2个对象时,它只是比较2个整数,它指向存储对象的内存,我们都知道整数比较是如何工作的。跨度>
    【解决方案3】:

    打印时查看值。注意到“对象 C at”旁边的十六进制数字了吗?那是一个指针引用。它可以大致等同于创建顺序。如果您遍历该列表,您会看到它已使用该列表作为标准对对象进行了排序。

    作为旁注,我记得在 Python 2.x 比较中是 confused...但我不知道这是否在 Py3k 中得到修复。

    【讨论】:

    • 是的,我注意到了。但原因是什么?
    • @aix 查看编辑。 Python stackoverflow.com/questions/4266918/…
    • 基本原理是python中的变量是对堆中对象的引用。按内存地址排序可能是 Python 开发人员能想到的最容易实现的默认行为。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-07-02
    • 1970-01-01
    • 2020-07-07
    相关资源
    最近更新 更多