如何在python中使两个对象具有相同的id?

2024-10-17 21:41:54 发布

您现在位置:Python中文网/ 问答频道 /正文

如果我有以下课程:

class Point(object):
    def __init__(self, x, y):
        self.x = x
        self.y = y

有两个对象:

^{pr2}$

如何修改类点使id(a) == id(b)?在


Tags: 对象selfidobjectinitdefclass课程
3条回答

您需要有一个对象的全局字典,并通过工厂函数(或自定义的__new__)获取它们,请参阅其他答案)。另外,考虑使用^{},这样就不会不必要地用不再需要的对象填满内存。在

from weakref import WeakValueDictionary


class _Point(object):
    def __init__(self, x, y):
        self.x = x
        self.y = y

# Cache of Point objects the program currently uses
_points = WeakValueDictionary()


def Point(x, y):
    """Create a Point object"""
    # Note that this is a function (a "factory function")
    # You can also override Point.__new__ instead
    try:
        return _points[x, y]
    except KeyError:
        _points[x, y] = point = _Point(x, y)
        return point


if __name__ == '__main__':
    # A basic demo
    print Point(1, 2)
    print id(Point(1, 2))
    print Point(2, 3) == Point(2, 3)

    pt_2_3 = Point(2, 3)

    # The Point(1, 2) we created earlier is not needed any more.
    # In current CPython, it will have been been garbage collected by now
    # (but note that Python makes no guarantees about when objects are deleted)
    # If we create a new Point(1, 2), it should get a different id

    print id(Point(1, 2))

请注意,namedtuple不能与WeakValueDictionary一起使用。在

如果需要比较两个对象是否包含相同的,则可以实现eq operator

>>> class Point(object):
...     def __init__(self, x, y):
...         self.x = x
...         self.y = y
...     def __eq__(self, other):
...         return self.x == other.x and self.y == other.y
...
>>> a = Point(1,2)
>>> b = Point(1,2)
>>> a == b
True
>>> b = Point(2,2)
>>> a == b
False
class Point(object):
    __cache = {}
    def __new__(cls, x, y):
        if (x, y) in Point.__cache:
            return Point.__cache[(x, y)]
        else:
            o = object.__new__(cls)
            o.x = x
            o.y = y
            Point.__cache[(x, y)] = o
            return o


>>> Point(1, 2)
<__main__.Point object at 0xb6f5d24c>
>>> id(Point(1, 2)) == id(Point(1,2))
True

当您需要一个真正简单的类,如Point,请始终考虑collections.namedtuple

^{pr2}$

我在namedtuple旁边使用了一个函数,因为它在IMO中更简单,但如果需要,可以很容易地将其表示为类:

class Point(namedtuple('Point', 'x y')):
    __cache = {}
    def __new__(cls, x, y):
        return Point.__cache.setdefault((x, y), 
                                         super(cls, Point).__new__(cls, x, y))

正如@PetrViktorin在他的answer中指出的那样,您应该考虑使用^{},因此删除的类实例(显然与namedtuple无关)不会保留在内存中,因为它们仍然在字典中被引用。在

相关问题 更多 >