我想知道是否有理由使用deepcopy而不是这样:list1 = [[1,2],[3,4],[5,6]]
list2 = eval(str(list1))
如果有其他很酷的方法,我很想知道。
使用eval要慢得多,因为它需要解析字符串并对其进行解释,而deepcopy不需要此步骤,而且您还需要预先转换为字符串,而deepcopy也不需要此转换。
这是我的机器上的两个结果:
>>> timeit.timeit('copy.deepcopy(ls)', setup='import copynls = [[1,2], [3,4]]')
3.9644698999999974
>>> timeit.timeit('eval(str(ls))', setup='ls = [[1,2], [3,4]]')
8.982202999999998
如果您刚刚获得(非复杂(list of lists
,则通过列表理解复制似乎比eval
:更快、更安全
import timeit
import json
import ujson
import copy
def _eval(l):
return eval(str(l))
def _copy(l):
return copy.deepcopy(l)
def _json(l):
return json.loads(json.dumps(l))
def _ujson(l):
return ujson.loads(ujson.dumps(l))
def _comp(l):
return [x[:] for x in l]
shortList = [[1, 2], [3, 4], [5, 6]]
longList = [[x, x + 1] for x in range(0, 50000)]
for lst in (shortList, longList):
for func in ("_eval", "_copy", "_json", "_ujson", "_comp"):
t1 = timeit.Timer(f"{func}({lst})", f"from __main__ import {func}")
print(f"{func} ran:", t1.timeit(number=1000), "milliseconds")
退出(短名单(:
_eval ran: 0.009196660481393337 milliseconds
_copy ran: 0.005948461592197418 milliseconds
_json ran: 0.004726926796138287 milliseconds
_ujson ran: 0.0011531058698892593 milliseconds
_comp ran: 0.00045751314610242844 milliseconds
输出(长列表(:
_eval ran: 16.720303252339363 milliseconds
_copy ran: 7.898970659822226 milliseconds
_json ran: 2.1138144126161933 milliseconds
_ujson ran: 1.2348785381764174 milliseconds
_comp ran: 0.5541304731741548 milliseconds
除了性能之外,还有很多很好的理由不使用eval
。关于一般的缺点,请看这里。
特别是关于你的例子,我想强调一个例子,事情出了严重的问题。想象一下,有一个类Foo
,它存储任意值x
:
class Foo:
def __init__(self, x):
self.x = x
def __repr__(self):
return f'{self.__class__.__name__}'
现在成像,您可以创建此类对象的列表,例如:
foos = [Foo(i) for i in range(5)]
如果您现在使用eval
,试图创建列表的副本,结果将不会被请求到原始列表:
test = eval(str(foos))
您最终得到的不是Foo
对象的列表,而是class types
:的列表
foos = [Foo(i) for i in range(5)]
print(foos)
# [Foo, Foo, Foo, Foo, Foo]
print(foos[0].x)
# 0
test = eval(str(foos))
print(test)
# [<class '__main__.Foo'>, <class '__main__.Foo'>, <class '__main__.Foo'>, <class '__main__.Foo'>, <class '__main__.Foo'>]
print(test[0].x)
# AttributeError: type object 'Foo' has no attribute 'x'