是否可以接受列表作业的复制?
Is Copying for List Assignments acceptable?
考虑以下最小示例:
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 文档说:
Assignment statements in Python do not copy objects, they create bindings between a target and an object.
应用上面的 class 意味着:
>>> 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 中的 class 来说,这是可以接受的行为吗?
这本身并没有错。只要您的 class 有据可查,如果您有充分的理由这样做,那就去做吧。考虑以下来自标准库 shelve
模块的 class,它本质上提供了一个 dict-like 数据库接口。由于使用 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__
。
考虑以下最小示例:
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 文档说:
Assignment statements in Python do not copy objects, they create bindings between a target and an object.
应用上面的 class 意味着:
>>> 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 中的 class 来说,这是可以接受的行为吗?
这本身并没有错。只要您的 class 有据可查,如果您有充分的理由这样做,那就去做吧。考虑以下来自标准库 shelve
模块的 class,它本质上提供了一个 dict-like 数据库接口。由于使用 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__
。