gpt4 book ai didi

python - 如何避免在 python 中作为参数传递时进行惰性属性评估

转载 作者:太空宇宙 更新时间:2023-11-04 08:45:51 25 4
gpt4 key购买 nike

我有以下代码用于在 python 3.5 中延迟计算一个值。我也试过 @cached_property decorator结果相同,因此为简单起见,我将使用它。

class Foo:    
@property
def expensive_object(self):
if not hasattr(self, "_expensive_object"):
print("Lengthy initialization routine")
self._expensive_object = 2
return self._expensive_object

问题是当我将它作为参数传递给函数时它会被求值,即使它最终没有在内部使用,如本例所示:

def bar(some_parameter, another_parameter):
if some_parameter != 10:
print(some_parameter)
else:
print(another_parameter)

从下面的输出中我们看到它只是通过传递才被评估,但这并不是绝对必要的,因为代码没有尝试使用它。

In [23]: foo1 = Foo()
...: bar(3, foo1.expensive_object)
Lengthy initialization routine
3

In [24]: bar(3, foo1.expensive_object)
3

在某些情况下,我的脚本可以在不需要评估的情况下运行,但由于这种情况,它最终还是会这样做。分解参数也是不切实际的。我还在组合成员对象的 __init__ 中使用它。

如果可能的话,我想让这个属性更加惰性,因为它应该只在实际读取时计算。

最佳答案

Python 在您寻求的级别上缺乏简单、惯用的惰性属性评估。

像这样获得惰性属性评估的方案有多种,但它们都涉及被调用函数(bar)的参与和协作。例如。你可以传入一个对象和一个属性名

def bar2(x, y, propname):
if x != 10:
print(x)
else:
print(getattr(y, propname))

bar2(3, foo1, 'expensive_object')

或者你可以像 lambda 一样传入一个可调用对象:

def bar3(x, y):
if x != 10:
print(x)
else:
print(y())

bar3(3, lambda: foo1.expensive_object)

但就其所有改进而言,Python 本质上是一种非常简单的语言。它不会做很多不需要评估的事情即使是最简单的 C 或 Java 编译器的优化例行公事。它不维护几乎形而上学的左值/右值你在 Perl 中看到的区别(这在这里真的很有帮助)。而且它不会尝试动态插入和评估 thunks延迟属性调用。当您调用 foo1.expensive_object 时,它将计算该值并交给我。如果你想以不同的方式完成它,你将不得不重要的其他安排,例如上述。

如果您经常需要延迟/惰性求值,那么定义一个必要时求值辅助函数会很方便:

def get_value(x): 
return x() if hasattr(x, '__call__') else x

这样您就可以在需要时稍微规范化对 y 的评估。 using 函数仍然需要配合,但这允许您在需要时传入静态值,或者在需要使评估更惰性时传入 lambda:

def bar4(x, y):
if x != 10:
print(x)
else:
print(get_value(y))

bar4(3, 33) # works
bar4(4, lambda: foo1.expensive_object) # also works!

关于python - 如何避免在 python 中作为参数传递时进行惰性属性评估,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40688473/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com