【问题标题】:Assigning an (OOP) object to another将(OOP)对象分配给另一个
【发布时间】:2017-11-21 19:36:06
【问题描述】:

我试图使用下面的replace_object() 之类的成员函数将一个Python 对象分配给另一个就地。但是,如您所见,object_A 保持不变,复制object_B 的唯一方法是创建一个全新的对象object_C,这违背了就地分配的目的。

这里发生了什么,我该如何就地进行分配?

class some_class():

    def __init__(self, attribute):

        self.attribute = attribute

    def replace_object(self, new_object):

        self = new_object

        # Does this line even have any effect?
        self.attribute = new_object.attribute 

        self.new_attribute = 'triangle'

        return self

object_A = some_class('yellow')
print(object_A.attribute)       # yellow
object_B = some_class('green')
object_C = object_A.replace_object(object_B)
print(object_A.attribute)       # yellow
print(object_C.attribute)       # green

#print(object_A.new_attribute)  # AttributeError!
print(object_B.new_attribute)   # triangle
print(object_C.new_attribute)   # triangle

我也尝试过使用copy.copy() 处理深层副本,但无济于事。

一个有趣的转折是,如果我替换

object_C = object_A.replace_object(object_B)

object_A = object_A.replace_object(object_B)

然后我得到我想要的。但是为什么replace_object()中的self = new_object语句不能达到同样的结果呢?

PS:我有一个很好的理由来做这个就地分配,所以虽然这可能不是一般的最佳实践,但在这里跟我一起去吧。

【问题讨论】:

  • 这不是 Python 中赋值的工作方式,即使对于专家来说,尝试改变这些语言机制也不太可能顺利。 Here's a quick guide to what assignment actually does in Python.
  • 你能解释一下为什么你认为你需要这样做吗?
  • @ScottHunter ...因为显而易见的替代方案,即object_A = object_A.replace_object(object_B),似乎是多余的。
  • 为什么不能只复制所有属性以镜像传入对象中的属性,或者您正在定义“平等”。
  • 正如我已经解释的那样,那是因为你这样做了self = new_object。不要那样做,因为现在当你这样做时:self.attribute = new_object.attribute 该语句等同于 new_object.attribute = new_object.attribute,即完全没有意义。

标签: python python-3.x oop


【解决方案1】:

您不能“将一个对象分配给另一个对象”。您可以将新的和现有的对象分配给新的和现有的名称。

self = new_object 只说'从现在起名称self 将引用new_object',并且对旧对象没有任何作用。 (注意self 只是一个变量名,和其他变量名一样,只是按照惯例指的是类定义中的对象。)

后续命令self.attribute = new_object.attribute 无效,因为self 已经成为new_object 的重复标签。

您可以将新对象的所有属性复制到旧对象。您最终会得到两个具有不同名称和相同属性的不同对象。除非您为这些对象overrode the equality operator,否则相等性测试 (a == b) 将返回 false。

要内联复制所有属性,您可以执行this 之类的操作:

def replace_object(self, new_object):
    self.__dict__ = new_object.__dict__.copy() # just a shallow copy of the attributes

很可能有更好的方法来做你想做的任何事情。

【讨论】:

  • 那么有什么选择呢? object_A = object_A.replace_object(object_B) 不是既多余又不优雅?
  • 我已经编辑了答案,并提出了如何复制属性的建议。但是很难看到这是一种有用的方法。
  • 可以的,谢谢。但是为什么它必须是浅拷贝呢?为什么不只是self.__dict__ = new_object.__dict__
  • 如果这样做,那么旧对象的属性字典将始终指向新对象的属性字典(两个名称都指向同一个对象)。例如。如果你输入 new_object.x = 30 那么你会发现 old_object 现在也有一个属性 x 等于 30。也许这就是你想要的?
  • 实际上,我只是选择循环遍历所有属性并改用__setattr__()。这是 kocher 还是我仍然做错了什么?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2016-06-24
  • 2020-11-10
  • 2011-12-24
  • 2019-12-27
  • 2021-05-02
  • 2012-01-06
  • 1970-01-01
相关资源
最近更新 更多