_azy-_oad-一个允许延迟计算表达式的极简接口。附加的函数和包装器允许它轻松地对函数和类使用延迟计算。
lazy-load的Python项目详细描述
允许对表达式和函数调用进行延迟计算的极简接口。
注意:这个小库高度基于python惰性对象代理。
为什么使用_azy-_oad?一般来说,延迟加载可以使一些软件实现更加高效。 尤其是在不知道是否需要加载某些数据的情况下。结果代码通常效率较低, 因为使用了紧急加载,或者代码不优雅,因为必须(以某种方式)对延迟加载进行编程。
这个库的优点是可以非常优雅和有效地使用延迟加载。
示例
在一个循环中,可能会出现一次甚至更频繁的特殊情况。如果是这样的话, 调用昂贵的函数 待完成。如果昂贵的函数必须多次调用,则结果对象可能会被重用。
可能的实现:
defexpensive_function():print("function evaluation")...returnresultobj=Noneforx,y,pinget_coordinates():iftest_for_something(x,y,p):ifobjisNone:obj=expensive_function()obj.do_something(x,y)
给定这个库,可以这样做:
fromlazy_loadimportlazydefexpensive_function():print("function evaluation")...returnresultobj=lazy(expensive_function)forx,y,pinget_coordinates():iftest_for_something(x,y,p):obj.do_something(x,y)
循环之外也有类似的情况。没有延迟加载的实现可能如下所示:
defexpensive_function():print("function evaluation")...returnresultobj=Nonedefget_obj():globalobjifobjisNone:obj=expensive_function()returnobjifcondition_a:get_obj().xyz()ifcondition_b:do_something()ifcondition_c:get_obj().abc()
使用惰性加载可以更容易地实现此代码。不仅代码更短,而且可读性更强:
fromlazy_loadimportlazydefexpensive_function():print("function evaluation")...returnresultobj=lazy(expensive_function)ifcondition_a:obj.xyz()ifcondition_b:do_something()ifcondition_c:obj.abc()
这可能是这样的情况,即昂贵的函数被更频繁地使用,并且总是进行惰性的计算。 在这种情况下,可以使用decorator来指示对该函数的所有函数调用都是惰性的。 评价的。这使得正常使用该功能成为可能。其行为与第一个示例中的相同:
fromlazy_loadimportlazy_func@lazy_funcdefexpensive_function():print("function evaluation")...returnresultobj=expensive_function()forx,y,pinget_coordinates():iftest_for_something(x,y,p):obj.do_something(x,y)
函数/方法调用的延迟求值可以使用@lazy\u funcdecorator和lazy调用来完成。这已经是 因此,下面的示例演示如何对函数调用执行一次性延迟计算:
fromlazy_loadimportlazy,lzdefexpensive_func(x,y):print(f"function evaluation with arguments x={x}, y={y}")...returnresult# Possibility 1: Use `lazy` with a callableobj=lazy(lambda:expensive_func(a,b))# Possibility 2: If it doesn't matter if the argument expressions for the expensive-function are eager evaluated, the call may be simplified:obj=lazy(expensive_func,a,b)# Possibility 3: `lazy` has a short version / alias: `lz`obj=lz(expensive_func,a,b)
python允许它传递函数:这通常用于回调,也用于其他用例。 假设一个昂贵的函数被传递给一个调用这个函数并存储 属性中的函数调用。稍后可能会使用此属性。取决于 程序流也可能发生此属性未使用的情况。对于一个延迟评估的函数 昂贵的函数调用只有在真正使用结果时才会执行。懒散评估的版本 函数与原始函数具有完全相同的签名。
现在人们可能希望能够动态地将一个callable转换为一个延迟计算的callable。 这可以通过以下方式完成:
fromlazy_loadimportlazy_func,lfdefexpensive_func(x):print(f"function evaluation with argument x={x}")...returnresult# Possibility 1: Use `lazy_func`.my_obj.do_something(f=lazy_func(expensive_func))# Possibility 2: Use `lf` which is an alias of `lazy_func`my_obj.do_something(f=lf(expensive_func))# Possibility 3: Use the `ℒ`-"operator"my_obj.do_something(f=ℒ[expensive_func])
实际上,我想更深入地研究“azy”或“azy”运算符。此运算符动态转换函数 到一个被延迟评估的函数。另一个例子:
fromlazy_loadimportℒdeftest(name):print(f"hey {name}")returnTrueres=test("peter")# prints "hey peter"test_l=ℒ[test]res=test_l("hans")# prints nothingifres:print("res is True")# prints "hey hans\nres is True"
也可以使用将多个函数转换为惰性计算的函数
最后,我们可能希望用一种方式来修饰一个类,它的所有公共方法都有一个返回
价值被懒散地评估。公共方法是所有名称不以\cite>开头的方法。
具有返回值的方法由给定的返回类型提示标识,该提示不能是none。
这种行为可以通过@lazy\u类-decorator(别名:lc): 最后,还可以使用force-eval(别名fe)强制计算延迟加载对象。
这个函数可以安全地用于非延迟加载对象:它就等于identity函数。 force\u eval函数也可以应用于惰性函数(使用惰性函数(x),@惰性函数创建的函数)
或者用〈cite〉〈cite〉)。这家酒馆res原始的非惰性/渴望函数。对于非惰性函数,此调用无效: pip安装延迟加载fromlazy_loadimportℒdeff1(x):print(f"f1 {x}")returnTruedeff2(x):print(f"f1 {x}")returnTruef1_l,f2_l,f3_l=ℒ[f1,f2,lambdax:x==1]# This is equal to:f1_l=ℒ[f1]f2_l=ℒ[f2]f3_l=ℒ[lambdax:x==1]
fromlazy_loadimportlazy_class@lazy_classclassMyClass:def__init__(self):# Method name starts with "_" => is not public; therefore it is eager evaluatedpassdefsetX(x)->None:# Method does not return a value => therefore it is eager evaluated...defdo():# Method does not hav a return value type hint => therefore it is eager evaluated...defcompute()->int:# Method will always be lazily evaluated...returnresult
fromlazy_loadimportlazy,force_evaldeff1(x):print(f"f1 {x}")returnTruelazy_obj=lazy(f1,1)# The following expression prints "f1 1" and returns "True"force_eval(lazy_obj)
fromlazy_loadimportlazy_func,force_eval@lazy_funcdeff(x):print("hey")returnx**2# The following line prints nothingobj=f(2)f_eager=force_eval(f)# The following line prints "hey" and "obj" has immediatly the value "4"obj=f_eager(2)
安装
要求
python 3.6或python3.7。
许可证
麻省理工学院