重复相同的对象

时间:2016-03-31 15:16:27

标签: python oop reference

我有两种对象:

class A(object):
    def __init__(self, name):
        self.name = name
        self.x = 0
        self.y = 0

    def __eq__(self, other):
        return isinstance(other, self.__class__) and self.name == other.name

    def __hash__(self):
        return hash(self.name)

我有另一个用两个对象定义的对象A:

class B(object):
    def __init__(self, objectA1, objectA2):
        self.objectA1 = objectA1
        self.objectA2 = objectA2

我的问题是,如果我这样做:

a = A("name")
b = B(A("name"), A("other"))

然后两个A("名称")相等(根据我定义的相等)但不指向同一个对象:我有

b.objectA1 is a == False

这是一个问题,因为我想访问b.objectA1.x和b.objectA1.y,我希望它们是a的x和y。

我知道这是一个参考问题,但我不知道如何修复它以获得我想要的东西,即

A("name") is A("name") == True 
始终

,即使A用B定义。

精度:一切都是从tkinter接口定义的,带有字符串。 我想我可以做一个字典d,其中键是字符串(对象A的名称),以及哪些值是关联对象A. 然后我会定义:

b = B(d["s1"], d["s2"])

然而,它看起来很难看,而且我正在寻找pythonic方法(我对OOP不是很熟悉)

由于

2 个答案:

答案 0 :(得分:2)

我不确定这是否是一个好主意,但您可能会混淆__new__方法,并检查之前是否创建了具有相同参数的实例:

class A(object):
    pool = {}

    def __new__(cls, *args, **kwargs):
        key = tuple(args)
        if key not in A.pool:
            A.pool[key] = super(A, cls).__new__(cls)
        return A.pool[key]

    # rest is the same as in your class

示例:

>>> A("foo") is A("bar")
False
>>> A("foo") is A("foo")
True

请注意,此仍然为从__init__检索到的对象调用pool,因此会初始化两次。此外,这仅在对象不可变时才有效;如果在初始化后两个实例等于,它们将保持不同的实例。

答案 1 :(得分:2)

如果您不熟悉Python的OOP,那么像元类这样的东西对您来说有点好笑,那么接受tobias_k建议:使用工厂。它可以是这样简单的功能:

class A(object):
    def __init__(self, name):
        self.name = name

def factory(name, pool={}):
    if name not in pool:
        pool[name] = A(name)
    return pool[name]

a = factory("foo")
b = factory("bar")
c = factory("foo")

assert a is a
assert a is not b
assert a is c

另外,我刚刚看到你对更多Pythonic方式的评论,然后将对象存储在字典中。运营商"是"比较两个对象的id()返回值。在CPython中,它对于每个对象都是唯一的,而不是在对象的生命周期中改变。你能得到的最好的方法是在某处存储实例。