在这种情况下,差异可能最好通过一个简单的绘图示例来理解。
首先有状态例如:
import matplotlib.pyplot as plt
plt.figure()
plt.plot([0,1], [1,0])
然后无状态(或者更确切地说,面向对象的方法):
import matplotlib.pyplot as plt
fig = plt.figure()
ax = fig.add_subplot(111)
li = ax.plot([0,1], [1,0])
这些执行相同的步骤:
- 创建数字对象(
matplotlib.figure.Figure
)
- 创建一个新的绘图区域对象(
matplotlib.axes.AxesSubplot
),并把它添加到图
- 创建一个新的行成绘图区(
matplotlib.lines.Line2D
)
在面向对象的形式,我们做上述操作相当明确,并采取对象引用变量(fig
,ax
,li
)。引用在有状态接口中也不会丢失,但它们隐藏在matplotlib
的某处。
当我们尝试改变某些属性时,图的大小。用OO方法:
fig.set_size_inches([10, 8])
有了有状态的方法,我们首先需要找到这个数字。有一个功能, plt.gcf
。所以:
plt.gcf().set_size_inches([10,8])
几乎是一回事。在我们同时开放多个数字的情况下,“几乎”部分变得非常重要。 plt.gcf
返回'当前'数字,但很难确定哪一个是当前数字。
同样的情况用轴或线重复。如果我们想调整绘图的x刻度,那么:
ax.set_xticks([0,.5,1])
是非常简单的。通过有状态的方法,它变为:
plt.gca().set_xticks([0, .5, 1])
其中gca()
返回'当前'轴。如果你有几个子图,这会变得非常复杂。
所以,问题是谁拿着物品。有状态接口仅仅是面向对象信息的薄包装。所有参数都在对象中,并且在一个绘图中有很多对象(数百甚至数千)。
matplotlib
有状态接口的一点是它经常与在IPython
中运行的pylab
一起使用。这提供了有状态接口以及一些带有命名空间的快捷方式。绘制正弦曲线一样简单:
x = linspace(0, 2*pi, 100)
plot(x, sin(x))
这无疑是比简单:
import numpy as np
import matplotlib.pyplot as plt
x = np.linspace(0, 2*np.pi, 100)
fig = plt.figure()
ax = fig.add_subplot(111)
li = ax.plot(x, np.sin(x))
不过,虽然通过pylab
提供的快捷方式是非常方便的互动工作,这是不是在脚本不错。我也使用pylab
,但是我在面向对象的表单中显示了我的matplotlib
相关答案中的几乎所有示例,因为它更透明。
这里有一个很好的解释[这里](http://en.wikipedia.org/wiki/State_(computer_science))。除了CS /编程世界之外,我还没有看到在英语中任何其他地方使用过的词。也许有人在[english.se]会更好... – ElGavilan
这是matplotlib记住你绘制的数字。除非你说'plt.close()'你先前绘制的数字仍然在记忆中。这并不是一个大问题,当你绘制一些图像时,但是当运行一个循环和绘制很多图像时,它会消耗大量的内存 – ThePredator
我不知道matplotlib,但通常状态意味着某种状态被记录,一种当前'会话'隐含的上下文。我通常了解有状态与无状态相反,在每个调用/使用中,由于不存在,您必须提供完整的上下文。这是一个快速的评论,如果你可以附上pyplot教程的url来确认。 –