在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现在检查是的,现在工作。