我目前正在阅读斯坦福大学给出的tensorflow教程lecture .它正在教授一个叫做“延迟加载”的概念。在幻灯片中,它解释了我们可以通过利用 python 的属性来避免这种情况。
我对 Python 比较陌生,他说的属性到底是什么?
Use Python property to ensure function is also loaded once the first time it is called*
最佳答案
关于使用 @property 装饰器进行惰性求值有一个很好的描述 here .基本上,@property 装饰器允许您定义一个实例变量,它将:
- 在第一次调用时进行评估(即延迟加载)
- 然后将结果存储在一个实例变量中,以便在进一步调用时引用。
要了解这一点,请考虑代码(请注意,此代码是从上一个链接中提取和更改的,因此应归功于 Steven Loria):
class Node_normal:
def __init__(self):
print("nn")
self.val = 2
class Node_lazy:
def val(self):
print("nl")
return 2
class Node_property:
def __init__(self):
self._val = False
@property
def val(self):
if not self._val:
print("np")
self._val = 2
return self._val
当一个Node_normal对象被实例化时,self.val将被初始化并立即赋值2(正常加载),而Node_lazy将被实例化但不赋值。相反,它会在调用 val() 时返回值(延迟加载)。最后,当 Node_property 被实例化时,self._val 将被初始化为一个默认值 (False),并且在调用时分配真值 (2) 并将其存储在 self._val 中以供进一步调用时再次引用。
您可以使用以下方法进行测试:
exec(open("node_normal.py").read())
exec(open("node_lazy.py").read())
exec(open("node_property.py").read())
class Graph:
def __init__(self):
nn = Node_normal()
self.nodes1 = [nn.val for x in range(1,10)]
nl = Node_lazy()
self.nodes2 = [nl.val() for x in range(1,10)]
np = Node_property()
self.nodes3 = [np.val for x in range(1,10)]
g = Graph()
print(g.nodes1)
print(g.nodes2)
print(g.nodes3)
给出结果
nn
nl
nl
nl
nl
nl
nl
nl
nl
nl
np
[2, 2, 2, 2, 2, 2, 2, 2, 2]
[2, 2, 2, 2, 2, 2, 2, 2, 2]
[2, 2, 2, 2, 2, 2, 2, 2, 2]
请注意,g.nodes 中的值对于所有三种方式都是相同的,但是 Node_normal 和 Node_property 只需要运行一次赋值,而 Node_lazy 进行了 10 次赋值。此外,在调用 np.val 之前,Node_property 不会将 2 分配给 self._val。这在分配值是一个昂贵的调用时最有用(这里不是这种情况)。
使用@property 装饰器还有其他原因,see here .
关于Python:如何确保函数在第一次调用时加载一次?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50479582/