在Python中传递到函数时,创建嵌套字典的副本或直接访问它是否更快?
我将一个字典(其中一个元素也是字典)传递给一个函数。 我想在函数中多次访问嵌套字典,在Python中传递到函数时,创建嵌套字典的副本或直接访问它是否更快?,python,python-3.x,Python,Python 3.x,我将一个字典(其中一个元素也是字典)传递给一个函数。 我想在函数中多次访问嵌套字典, 所以我想知道在一开始就创建一个嵌套字典的副本作为局部变量,并从那以后直接访问它是否会更快, 或者每次都通过外部字典访问它。如果您有此代码: d={'nested':{},1:[],2:[],3:[] 定义f(d): n=d[“嵌套的”] 对于n.项()中的k,v: ... 然后调用f(d)是便宜的,因为对d的引用是作为参数复制的,但只需要花费int的大小 行n=d['nested']查找密钥需要花费一点时间。
所以我想知道在一开始就创建一个嵌套字典的副本作为局部变量,并从那以后直接访问它是否会更快, 或者每次都通过外部字典访问它。如果您有此代码:
d={'nested':{},1:[],2:[],3:[]
定义f(d):
n=d[“嵌套的”]
对于n.项()中的k,v:
...
然后调用f(d)
是便宜的,因为对d
的引用是作为参数复制的,但只需要花费int
的大小
行n=d['nested']
查找密钥需要花费一点时间。此费用最好在函数开始时支付一次,而不是每次访问n
时支付。如果您有此代码:
d={'nested':{},1:[],2:[],3:[]
定义f(d):
n=d[“嵌套的”]
对于n.项()中的k,v:
...
然后调用f(d)
是便宜的,因为对d
的引用是作为参数复制的,但只需要花费int
的大小
行
n=d['nested']
查找密钥需要花费一点时间。此费用最好在函数开始时支付一次,而不是每次访问n
时支付。我知道您已经接受了答案。但你也要看到这一点。
有时,看到统计值来证实你的直觉是很好的。我写了一个操纵嵌套字典的小脚本。直觉是正确的,当您有一个嵌套字典的引用时,它花费的时间更少。这里是情节,阅读下面的细节,看看我是如何得到这个。
使用\u noRef
我不会保留对嵌套字典的引用。通过\u ref
我保留了对嵌套字典的引用。然后我运行for循环,将成员添加到add
中的嵌套字典中,并在count
中访问它们
我在有参考和无参考的情况下计时。为了进一步确定模式,我正在重复并获得多个时间值
这是剧本
import timeit
import matplotlib.pyplot as plt
def add_noRef(d):
for i in range(10000000):
d['nested'][i] = 100*i
def add_Ref(d):
r = d['nested']
for i in range(10000000):
r[i] = 100*i
def count_noRef(d):
count = 0
for i in range(10000000):
count += d['nested'][i]
return count
def count_Ref(d):
r = d['nested']
count = 0
for i in range(10000000):
count += r[i]
return count
def TEST_NO_REF(repeats):
SETUP_CODE = '''
def add_noRef(d):
for i in range(1000):
d['nested'][i] = 100*i
def count_noRef(d):
count = 0
for i in range(1000):
count += d['nested'][i]
return count'''
TEST_CODE = '''
d = dict()
d['nested'] = dict()
add_noRef(d)
x = count_noRef(d)
'''
# timeit.repeat statement
times = timeit.repeat(setup = SETUP_CODE,
stmt = TEST_CODE,
repeat = repeats,
number = 10000)
return times
def TEST_REF(repeats):
SETUP_CODE = '''
def add_Ref(d):
r = d['nested']
for i in range(1000):
r[i] = 100*i
def count_Ref(d):
count = 0
r = d['nested']
for i in range(1000):
count += d['nested'][i]
return count'''
TEST_CODE = '''
d = dict()
d['nested'] = dict()
add_Ref(d)
x = count_Ref(d)
'''
# timeit.repeat statement
times = timeit.repeat(setup = SETUP_CODE,
stmt = TEST_CODE,
repeat = repeats,
number = 10000)
return times
repeats = 10
X = [i for i in range(1,repeats+1)]
time_Norefs = TEST_NO_REF(repeats)
time_refs = TEST_REF(repeats)
plt.plot(X, time_Norefs)
plt.plot(X, time_refs)
plt.legend(["Without using reference to nested dict", "Using reference to nested dict"])
plt.xlabel('Iteration')
plt.ylabel('time taken')
plt.title('Time taken to execute')
plt.show()
plt.savefig('timeTest.png')
我看你已经接受了答案。但你也要看到这一点。 有时,看到统计值来证实你的直觉是很好的。我写了一个操纵嵌套字典的小脚本。直觉是正确的,当您有一个嵌套字典的引用时,它花费的时间更少。这里是情节,阅读下面的细节,看看我是如何得到这个。 使用
\u noRef
我不会保留对嵌套字典的引用。通过\u ref
我保留了对嵌套字典的引用。然后我运行for循环,将成员添加到add
中的嵌套字典中,并在count
中访问它们
我在有参考和无参考的情况下计时。为了进一步确定模式,我正在重复并获得多个时间值
这是剧本
import timeit
import matplotlib.pyplot as plt
def add_noRef(d):
for i in range(10000000):
d['nested'][i] = 100*i
def add_Ref(d):
r = d['nested']
for i in range(10000000):
r[i] = 100*i
def count_noRef(d):
count = 0
for i in range(10000000):
count += d['nested'][i]
return count
def count_Ref(d):
r = d['nested']
count = 0
for i in range(10000000):
count += r[i]
return count
def TEST_NO_REF(repeats):
SETUP_CODE = '''
def add_noRef(d):
for i in range(1000):
d['nested'][i] = 100*i
def count_noRef(d):
count = 0
for i in range(1000):
count += d['nested'][i]
return count'''
TEST_CODE = '''
d = dict()
d['nested'] = dict()
add_noRef(d)
x = count_noRef(d)
'''
# timeit.repeat statement
times = timeit.repeat(setup = SETUP_CODE,
stmt = TEST_CODE,
repeat = repeats,
number = 10000)
return times
def TEST_REF(repeats):
SETUP_CODE = '''
def add_Ref(d):
r = d['nested']
for i in range(1000):
r[i] = 100*i
def count_Ref(d):
count = 0
r = d['nested']
for i in range(1000):
count += d['nested'][i]
return count'''
TEST_CODE = '''
d = dict()
d['nested'] = dict()
add_Ref(d)
x = count_Ref(d)
'''
# timeit.repeat statement
times = timeit.repeat(setup = SETUP_CODE,
stmt = TEST_CODE,
repeat = repeats,
number = 10000)
return times
repeats = 10
X = [i for i in range(1,repeats+1)]
time_Norefs = TEST_NO_REF(repeats)
time_refs = TEST_REF(repeats)
plt.plot(X, time_Norefs)
plt.plot(X, time_refs)
plt.legend(["Without using reference to nested dict", "Using reference to nested dict"])
plt.xlabel('Iteration')
plt.ylabel('time taken')
plt.title('Time taken to execute')
plt.show()
plt.savefig('timeTest.png')
不需要复印件。只需引用嵌套的
dict
,并在整个函数中使用该引用。“更快地创建嵌套字典的副本”。几乎可以肯定,创建字典的实际[深度]副本不会更快。创建一个作为局部变量的额外引用可能会更快。您可能需要使用来查看它在您的情况下是否真正值得。我想创建一个只调用一次的引用会更快,但这取决于python处理字典的方式,也取决于所需的大小。速度的提高可能会最小。函数参数总是按值传递,只是每个值,在python中,是对对象的引用。这意味着传递参数总是便宜的,因为它相当于为平台传递本机int
。这是一项临时任务。你应该读一下:为了更清晰,不需要复印。只需引用嵌套的dict
,并在整个函数中使用该引用。“更快地创建嵌套字典的副本”。几乎可以肯定,创建字典的实际[深度]副本不会更快。创建一个作为局部变量的额外引用可能会更快。您可能需要使用来查看它在您的情况下是否真正值得。我想创建一个只调用一次的引用会更快,但这取决于python处理字典的方式,也取决于所需的大小。速度的提高可能会最小。函数参数总是按值传递,只是每个值,在python中,是对对象的引用。这意味着传递参数总是便宜的,因为它相当于为平台传递本机int
。这是一项临时任务。你应该读一下:为了更清楚。谢谢,这正是我面对的情况谢谢,这正是我面对的情况facing@Manuel现在检查是的,现在工作。@Manuel现在检查是的,现在工作。