Python列表的深拷贝赋值

6

我在一次Python考试中遇到了这个问题。试图返回一个类似于以下列表的深度副本:

l = list()
l = [0,1,2]
l1 = l
l[0] = 1
应该包含[0,1,2]而不是[1,1,2]

这个练习要求使用元类来实现。

class deep(type):
    def __new__(meta, classname, bases, classDict):
        return type.__new__(meta, classname, bases, classDict)
    def __init__(cls, name, bases, dct):
        super(deep, cls).__init__(name, bases, dct)
    def __call__(cls, *args, **kwds):
        return type.__call__(cls, *args, **kwds)            
class list(metaclass=deep):
    def __init__(self):
        pass

据我所知,在Python中,'='是一个语句而不是运算符,并且它无法被覆盖。有没有什么办法在赋值时返回深拷贝?我已经尝试了很多次,但都没有成功。

3
简而言之,你做不到。即使有些聪明的黑客找到了方法,也 永远不应该 使用。相信我,我不会轻易发表这样的断言。 - user395760
4
这是一个相当奇怪的练习,因为你可以使用切片符号(l1 = l[:])仅用三个字符执行深拷贝。在这里使用元类似乎有些过度设计。 - Frédéric Hamidi
如果这是一道学校考试题,我建议你直接关闭它。要求我们帮助你完成考试是学术作弊的顶峰。 - S.Lott
3
@S.Lott:也许考试已经结束了。但至少应该标记为“作业”或“考试”。 - ninjagecko
1
@Frederic Hamidi:也许在你的Python版本中可以这样做深层复制,但其他大多数人需要from copy import deepcopyb=deepcpy(a),否则只有主列表会被复制,而所有嵌套的容器类都将作为引用保留在新列表中!您可以通过例如以下方式检查它:for l in (a,b): id(l); map (id,l) - Don Question
显示剩余3条评论
2个回答

1
要理解 Python 中的 l1 = l 是什么意思,请阅读 其他语言有“变量”,Python 有“名称”
要更改 l[0] = 1 的作用,您可以重写 l__setitem__() 方法:
>>> class L(list):
...     def __setitem__(self, i, v):
...         list.__setitem__(self, i, 10)
... 
>>> l = L()
>>> l.append(1)
>>> l
[1]
>>> l[0] = 0
>>> l
[10]

如果想要改变l = List(); l = [0,1,2]的行为,可以在CPython中定义List.__del__()方法,并操纵l所属的命名空间,例如使用inspect模块。不用说,你永远不应该这样做。

>>> import inspect
>>> class L:
...     def __del__(self):
...         inspect.currentframe().f_globals['l'] = [1,2,3]
... 
>>> l = L()
>>> l = [0]
>>> l
[1, 2, 3]

1
据我所知,在Python中没有使用某种额外语法是不可能实现的。正如您所说,您无法覆盖=

但是他可以使用__repr__方法来实现类似的结果!只需返回一个新类而不是字符串! - Don Question
@DonQuestion:绑定名称时会调用__repr__吗?这似乎很奇怪。 - Daenyth
@Daenyth 不是这样的。Don Question 跑题了。 - user395760
@DonQuestion 我也尝试使用__repr__方法,通过返回copy.deepcopy(self),但是Python返回了:TypeError: repr returned non-string (type list),因为__repr__只接受字符串。 - amn
我不是指 repr(),而是带有两个下划线的特殊方法 __repr__。尽管 delnan 是正确的,因为这种复制方式似乎行不通。我之前没有测试过,所以我走错了方向。抱歉! - Don Question

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接