【问题标题】:Is Copying for List Assignments acceptable?是否可以复制列表分配?
【发布时间】:2020-11-24 22:00:28
【问题描述】:

考虑以下最小示例:

class MyClass():
    def __init__(self, length):
        self._list = [[] for _ in range(length)]
    def __setitem__(self, key, value):
        self._list[key] = value.copy()
    def __getitem__(self, key):
        return self._list[key]

现在,Python 文档说:

Python 中的赋值语句不会复制对象,它们会在目标和对象之间创建绑定。

应用上面的类意味着类似:

>>> l = [[1,2,3,4], [3,2,1,0]]
>>> C = MyClass(2)
>>> C[0] = l[0]

这确实是一个赋值语句。但是现在的值是副本:

>>> C[0] == l[0]
True
>>> C[0] is l[0]
False

对于 Python 中的类来说,这是可以接受的行为吗?

【问题讨论】:

  • 你为什么要这样做?
  • 这很难解释。我参与了 SageMath 项目,我们正在处理可变元素,即张量。
  • 我需要一个将张量保存在列表中的类。但这是一个全新的可变元素。与原始张量的联系可能会变得不可见。问题是通过复制进行列表分配是否是一种想要的行为。
  • 此外,我们想添加一个方法,使这个元素不可变。让张量在此过程中不可变可能对用户来说是不可取的。
  • 这是可以接受的,只是令人惊讶的行为。

标签: python copy variable-assignment assignment-operator


【解决方案1】:

这本身并没有错。只要您的课程有很好的文档记录,如果您有充分的理由这样做,那就去吧。考虑标准库shelve 模块中的以下类,它本质上提供了一个类似dict 的数据库接口。由于使用object[key] = value 将写入磁盘,而检索该对象将从磁盘检索它,因此它不会为您提供相同的对象(必须有缓存选项)!所以:

In [1]: import shelve

In [2]: data = [[1,2,3],[4,5,6]]

In [3]: database = shelve.open('db')

In [4]: database['key'] = data[0]

In [5]: database['key']
Out[5]: [1, 2, 3]

In [6]: database['key'] is data[0]
Out[6]: False

文档的那部分是指对变量的赋值语句,如下所示:

some_var = foo

确实,它从不复制。而且您无法真正改变这一点(嗯,也许,但这是另一个问题)。您可以随意实现__setitem____getitem__

【讨论】:

  • @YoungMath 呵呵,是的,通常,“这可以接受吗”是一个基于意见的边缘问题,但我认为“好吧,标准库做到了”与目标“没关系”一样接近” 原样。
猜你喜欢
  • 2018-10-25
  • 1970-01-01
  • 2021-04-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-04-28
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多