有没有更好的方法来创建延迟变量初始化?

net*_*vah 5 python variables lazy-evaluation

我想创建仅在我真正需要时才初始化变量的代码。但是以常规方式初始化:

var = None

if var is None:
    var = factory()
var2 = var
Run Code Online (Sandbox Code Playgroud)

在代码中制造太多噪音。

我试图创建快速解决方案,但我觉得有更好的选择。这是我的快速解决方案,但无法获取参数并为此使用 defaultdict。

def lazy_variable(factory):
    data = defaultdict(factory)
    return lambda: data['']

var = lazy_variable(a_factory)
var2 = var()
Run Code Online (Sandbox Code Playgroud)

更多问题:

  • 是否有仅包含一个变量的快速 python 容器?
  • 有没有办法在不调用带括号的函数的情况下返回值?

编辑:

请考虑性能。我知道我可以创建一个可以具有这种行为的类,但它比简单的解决方案和默认的 dict 解决方案慢。

尝试一些解决方案:

定义:

import cachetools.func
import random

@cachetools.func.lru_cache(None)
def factory(i):
    return random.random()
Run Code Online (Sandbox Code Playgroud)

并运行:

%%timeit

for i in xrange(100):
    q = factory(i)
    q = factory(i)
Run Code Online (Sandbox Code Playgroud)

得到了:

100 loops, best of 3: 2.63 ms per loop
Run Code Online (Sandbox Code Playgroud)

幼稚的:

%%timeit

for i in xrange(100):
    a = None
    if a is None:
        a = random.random()
    q = a
    q = a
Run Code Online (Sandbox Code Playgroud)

得到了:

The slowest run took 4.71 times longer than the fastest. This could mean that an intermediate result is being cached.
100000 loops, best of 3: 14.8 µs per loop
Run Code Online (Sandbox Code Playgroud)

我不确定缓存了什么

默认字典解决方案:

%%timeit

for i in xrange(100):
    a = lazy_variable(random.random)
    q = a()
    q = a()
Run Code Online (Sandbox Code Playgroud)

得到了:

The slowest run took 4.11 times longer than the fastest. This could mean that an intermediate result is being cached.
10000 loops, best of 3: 76.3 µs per loop
Run Code Online (Sandbox Code Playgroud)

天啊!

net*_*vah 1

好吧,我想我找到了一个使用生成器的又好又快的解决方案:

def create_and_generate(creator):
    value = creator()
    while True:
        yield value    


def lazy_variable(creator):
    generator_instance = create_and_generate(creator)
    return lambda: next(generator_instance)
Run Code Online (Sandbox Code Playgroud)

另一个快速解决方案是:

def lazy_variable(factory):
    data = []
    def f():
        if not data:
            data.extend((factory(),))
        return data[0]
    return f
Run Code Online (Sandbox Code Playgroud)

但我认为生成器更清晰。