Python在构造函数中对self的赋值不会使对象相同

时间:2015-02-15 22:25:45

标签: python constructor self

我正在使用Python构建一个构造函数。当使用现有对象作为其输入进行调用时,它应该设置" new"反对同一个对象。这是一个10行演示:

class A:
    def __init__(self, value):
        if isinstance(value, A):
            self = value
        else:
            self.attribute = value
a = A(1)
b = A(a)#a and b should be references to the same object
print("b is a", b is a)#this should be true: the identities should be the same
print("b == a", b == a)#this should be true: the values should be the same

我希望从现有对象A(a)构造的对象aa。为什么不呢?为了清楚起见,我希望A(a)引用与a相同的对象,而不是副本。

4 个答案:

答案 0 :(得分:7)

与任何其他参数一样,

self是函数或方法的局部变量之一。赋值给局部变量的裸名称永远不会影响该函数或方法之外的任何内容,它只是在本地重新绑定该名称。

正如评论正确地指出的那样,目前还不清楚为什么你不会这样做

b = a

假设你有合理的理由,你需要覆盖的不是__init__,而是__new__(然后在__init__中采取一些预防措施以避免双重初始化)。这不是一个明显的过程,所以我会等你解释你到底想要完成什么。

补充:明确了我同意OP的需要,工厂功能(理想情况下,我建议,作为一种类方法)更好 - 并且比__new__更清晰,这将起作用(毕竟是一种类方法,但是方式不那么清晰。

所以,我的代码如下:

class A(object):

    @classmethod
    def make(cls, value):
        if isinstance(value, cls): return value
        return cls(value)

    def __init__(self, value):
        self.attribute = value

现在,

a = A.make(1)
b = A.make(a)

完成OP的愿望,对传递给A.make的参数类型进行多态化。

答案 1 :(得分:3)

让它完全完全的唯一方法是实现__new__,构造函数而不是 __init__,初始化(如果两者都被实现,行为可能变得相当复杂)。实现__eq__进行平等比较也是明智之举,尽管这可以追溯到身份比较。例如:

>>> class A(object):
    def __new__(cls, value):
        if isinstance(value, cls):
            return value
        inst = super(A, cls).__new__(cls)
        inst.attribute = value
        return inst
    def __eq__(self, other):
        return self.attribute == other.attribute


>>> a = A(1)
>>> b = A(a)
>>> a is b
True
>>> a == b
True
>>> a == A(1)
True  # also equal to other instance with same attribute value

你应该看一下data model documentation,它解释了可用的各种“魔法”以及它们的作用。参见例如__new__

答案 2 :(得分:2)

__init__是初始值设定项,而不是构造函数。你不得不与__new__混在一起做你想做的事情,去那里可能不是一个好主意。

尝试

a = b = A(1)

代替。

答案 3 :(得分:0)

如果您调用构造函数,它将创建一个新对象。最简单的方法是执行hacatu建议的操作,并简单地将b分配给一个值。如果没有,也许您可​​以使用if语句检查传入的值是否等于您想要引用的对象,如果是,则只需在调用构造函数之前返回该项。我没有经过测试,所以我不确定它是否有效。