懒惰评估Python字典

时间:2017-10-20 08:06:02

标签: python python-3.x

给出一直提到的词典:

def getMyDict():
    myDict = {};
    myDict['1'] = '1'
    return myDict

要访问我使用的字典值:

getMyDict()['1']

如何设计字典,以便只评估字典的创建一次。因此,对getMyDict['1']的多次调用不会导致多次调用myDict['1'] = '1'

来自Scala,可以使用lazy keyword:What does a lazy val do?

来完成

这个功能在Python中似乎不存在?

我找到的最近的是:Python lazy evaluator

上面的字典例子不是现实世界,而是设法说明这一点。

3 个答案:

答案 0 :(得分:2)

您可以使用此answer中描述的run_once装饰器的修改版本(下文)。

def run_once(f):
    def wrapper(*args, **kwargs):
        if not wrapper.has_run:
             wrapper.has_run = True
             wrapper.cache = f(*args, **kwargs)
        return wrapper.cache
    wrapper.has_run = False
    return wrapper

@run_once
def getMyDict():
    myDict = {}
    myDict['1'] = '1'
    print('Run getMyDict')
    return myDict


print(getMyDict()['1'])
print(getMyDict()['1'])
print(getMyDict()['1'])

输出:

Run getMyDict
1
1
1

我在这里假设你真正的getMyDict()函数是一个非常重量级的函数。这样的功能可能会生成一个庞大的字典,从磁盘或互联网等信息中获取信息。

<强>更新

这项技术也有效:

一个改进是重命名此函数以描述其真正的目的:

def initMyDict():
    myDict = {}
    myDict['1'] = '1'
    print('Run initMyDict')
    return myDict

现在函数的名称意味着它应该只运行一次。

现在让我们编写你想要调用的函数:

def getMyDict(myDict=initMyDict()):
    return myDict

让我们称之为:

print(getMyDict()['1'])
print(getMyDict()['1'])
print(getMyDict()['1'])

输出:

Run initMyDict
1
1
1

这种技术确实有两个缺陷:

  1. 每次程序运行时都会初始化dict
  2. 如果您提供参数,呼叫网站将返回参数。

答案 1 :(得分:1)

我也无法理解你的意思,但我试着理解。为了更清楚:

def Ops():
    print("Ops")

lazy_dict = {}
lazy_dict["Ops"] = Ops()  # not actually evaluate
...
print(lazy_dict["Ops"])   # run here

你是说像上面这样的东西吗?将值绑定到dict的键时,键只保留对此值的惰性引用,而不是实际值。

但它仍然被混淆,因为这是dict的行为或有价值的行为?

例如:

有一个lib为函数实现一个惰性包装器,如果你将一个惰性函数绑定到dict的键,它将完全是一个懒惰的评估:

import lazy

@lazy
def Ops():
    print("Ops")

lazy_dict = {}
lazy_dict["Ops"] = Ops()  # not actually evaluate
...
print(lazy_dict["Ops"])   # run here

答案 2 :(得分:1)

我从这个问题中理解的是,你想要创建一个函数来更新一个字典(并返回它),但你已经硬编码myDict['1'] = '1'

您想知道如何在其中加入其他值,而不是一次又一次地调用myDict['1'] = '1'

在我看来,你能做的就是传递函数中的值。

def getMydict(key=x, val=y):
    tempDict = {key: val}
    return tempDict

tempDict在函数内只有作用域,因此如果你想更新现有的dict,你也可以传递字典名称。

def getMydict(dictname=stuff, key=x, val=y):
    dictname.update({key: val})
    return dictname
希望有所帮助。