5

以下のようなクラスがある場合:

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

そして2つのオブジェクトがあります:

a = Point(1,2)
b = Point(1,2)

クラス Point を変更するにはどうすればよいid(a) == id(b)ですか?

4

3 に答える 3

9
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

from collections import namedtuple
def Point(x, y, _Point=namedtuple('Point', 'x y'), _cache={}):
    return _cache.setdefault((x, y), _Point(x, y))

>>> Point(1, 2)
Point(x=1, y=2)
>>> id(Point(1, 2)) == id(Point(1, 2))
True

より単純な IMO であるため、関数を一緒に使用しましたnamedtupleが、必要に応じてクラスとして簡単に表すことができます。

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が彼の回答weakref.WeakValueDictionaryで指摘したように、削除されたクラスのインスタンス(namedtuple明らかに動作しない)の使用は、辞書自体で参照されたままになるため、メモリに残らないことを考慮する必要があります。

于 2013-06-07T06:07:53.833 に答える
5

オブジェクトのグローバル ディクショナリが必要であり、ファクトリ関数 (またはカスタム__new__、他の回答を参照) を介してそれらを取得する必要があります。さらに、WeakValueDictionary不要になったオブジェクトでメモリが不必要にいっぱいにならないように、 を使用することを検討してください。

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 では機能しないことに注意してください。

于 2013-06-07T07:06:24.007 に答える