2013-06-07 3 views
4

나는 수업 아래와 같은 경우 :두 개의 객체를 파이썬에서 동일한 id로 만드는 방법은 무엇입니까?

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

그리고이 객체가 : 나는 클래스 포인트를 수정하는 방법

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

id(a) == id(b)을 만들 수 있습니까? 당신이 Point 같은 정말 간단한 클래스를 필요로 할 때

+3

이렇게하는 유일한 방법은 두 개체가 같은 개체가되도록 만드는 것입니다. 왜 이걸하고 싶어? – BrenBarn

+0

유일한 방법은 같은 개체에 대한 두 개의 참조를 갖는 것입니다. –

답변

8
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 

, 항상 IMO 간단하지만 필요한 경우 쉽게 클래스로 표현할 수 있기 때문에이 namedtuple 함께 기능을 사용 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 

고려 :

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과 작동하지 않음)는 사전 자체에서 참조 된 채 남아 있으므로 메모리에 남아 있지 않습니다.

+0

최소 공장에 대해 +1 – Marc

+1

아, 플라이급 패턴. 누군가'Point '를 서브 클래스 화하면 혼란을 피하기 위해 캐시'__cache'를 호출해야합니다. –

+0

@gnibbler 좋은 포인트 – jamylak

2

당신이 당신의 두 객체가 같은 을 수용 여부를 비교해야하는 경우 구현할 수있는 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 
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)) 

명명 된 튜플은 WeakValueDictionary에서 작동하지 않습니다.

+0

+1 좋은 생각입니다. – jamylak

관련 문제