[关闭]
@KarlYan95 2017-07-25T13:35:30.000000Z 字数 15029 阅读 713

Matplotlib: plotting 《Scipy Lecture Notes》

Python


matplotlib.org
Matplotlib: plotting


1 简介 Introduction

Matplotlib is probably the single most used Python package for
2D-graphics. It provides both a very quick way to visualize data from
Python and publication-quality figures in many formats. We are going
to explore matplotlib in interactive mode covering most common cases.
Matplotlib可能是2D图形中最常用的Python包。它提供了一个非常快速的方式来显示来自Python的数据和许多格式的数据。我们将以互动模式探索matplotlib,涵盖大多数常见的情况。

1.1 IPython与Matplotlib模式

IPython is an enhanced interactive Python shell that has lots of
interesting features including named inputs and outputs, access to
shell commands, improved debugging and many more. It is central to the
scientific-computing workflow in Python for its use in combination
with Matplotlib: For interactive matplotlib sessions with
Matlab/Mathematica-like functionality, we use IPython with it’s
special Matplotlib mode that enables non-blocking plotting.
IPython是一个增强的交互式Python外壳,具有许多有趣的功能,包括命名输入和输出,访问shell命令,改进的调试等等。它是Python中科学计算工作流的核心,它与Matplotlib结合使用:对于使用Matlab/Mathematica类功能的交互式matplotlib会话,我们使用IPython与特殊的Matplotlib模式,可以实现非阻塞绘图。

1.2 pyplot

pyplot provides a procedural interface to the matplotlib
object-oriented plotting library. It is modeled closely after Matlab™.
Therefore, the majority of plotting commands in pyplot have Matlab™
analogs with similar arguments. Important commands are explained with
interactive examples.
pyplot为matplotlib面向对象的绘图库提供了一个程序接口。它与Matlab™类似。因此,pyplot中的大多数绘图命令具有类似参数的Matlab™类似物。重要的命令用交互式示例进行说明。

习惯用法 from matplotlib import pyplot as plt


2 简单画图 Simple plot

In this section, we want to draw the cosine and sine functions on the
same plot. Starting from the default settings, we’ll enrich the figure
step by step to make it nicer.
在本节中,我们要在同一个图上画出余弦和正弦函数。从默认设置开始,我们将逐步丰富图形,使其更好。

  1. import numpy as np
  2. X = np.linspace(-np.pi, np.pi, 256, endpoint=True)
  3. C, S = np.cos(X), np.sin(X)

2.1 用默认设置画图 Plotting with default settings

Matplotlib comes with a set of default settings that allow customizing
all kinds of properties. You can control the defaults of almost every
property in matplotlib: figure size and dpi, line width, color and
style, axes, axis and grid properties, text and font properties and so
on.
Matplotlib带有一组允许自定义各种属性的默认设置。你可以控制matplotlib中几乎每个属性的默认值:图形尺寸和dpi,线宽,颜色和样式,轴,轴和网格属性,文本和字体属性等。

参考文档:
plot toturial
plot command

  1. import numpy as np
  2. import matplotlib.pyplot as plt
  3. X = np.linspace(-np.pi, np.pi, 256, endpoint=True)
  4. C, S = np.cos(X), np.sin(X)
  5. plt.plot(X, C)
  6. plt.plot(X, S)
  7. plt.show()

2.2 初始化默认设置 Instantiating defaults

直接上代码

  1. import numpy as np
  2. import matplotlib.pyplot as plt
  3. # Create a figure of size 8x6 inches, 80 dots per inch
  4. plt.figure(figsize=(8, 6), dpi=80)
  5. # Create a new subplot from a grid of 1x1
  6. # plt.subplot(rows, columns, position)
  7. plt.subplot(1, 1, 1)
  8. X = np.linspace(-np.pi, np.pi, 256, endpoint=True)
  9. C, S = np.cos(X), np.sin(X)
  10. # Plot cosine with a blue continuous line of width 1 (pixels)
  11. plt.plot(X, C, color="blue", linewidth=1.0, linestyle=":")
  12. # Plot sine with a green continuous line of width 1 (pixels)
  13. plt.plot(X, S, color="green", linewidth=1.0, linestyle="-")
  14. # Set x limits
  15. plt.xlim(-4.0, 4.0)
  16. # Set x ticks
  17. plt.xticks(np.linspace(-4, 4, 9, endpoint=True))
  18. # Set y limits
  19. plt.ylim(-1.0, 1.0)
  20. # Set y ticks
  21. plt.yticks(np.linspace(-1, 1, 5, endpoint=True))
  22. # Save figure using 72 dots per inch
  23. # plt.savefig("exercice_2.png", dpi=72)
  24. # Show result on screen
  25. plt.show()

2.3 改变颜色与线的宽度 Changing colors and line widths

  1. plt.figure(figsize=(10, 6), dpi=80)
  2. plt.plot(X, C, color="blue", linewidth=2.5, linestyle="-")
  3. plt.plot(X, S, color="red", linewidth=2.5, linestyle="-")

2.4 limits的设置 Setting limits

Current limits of the figure are a bit too tight and we want to make
some space in order to clearly see all data points.

  1. plt.xlim(X.min() * 1.1, X.max() * 1.1)
  2. plt.ylim(C.min() * 1.1, C.max() * 1.1)

2.5 Tick的设置 Setting ticks

  1. plt.xticks([-np.pi, -np.pi/2, 0, np.pi/2, np.pi])
  2. plt.yticks([-1, 0, +1])

ticks

2.6 Tick标签设置 Setting tick labels

Ticks are now properly placed but their label is not very explicit. We
could guess that 3.142 is π but it would be better to make it
explicit. When we set tick values, we can also provide a corresponding
label in the second argument list. Note that we’ll use latex to allow
for nice rendering of the label.
ticks现在已妥善设置,但标签不太明确。我们可以猜到3.142是π,但最好是明确表示。当我们设置tick值时,我们还可以在第二个参数列表中提供相应的标签。
注意,我们将使用latex来允许标签的漂亮渲染。

  1. plt.xticks([-np.pi, -np.pi/2, 0, np.pi/2, np.pi],
  2. [r'$-\pi$', r'$-\pi/2$', r'$0$', r'$+\pi/2$', r'$+\pi$'])
  3. plt.yticks([-1, 0, +1],
  4. [r'$-1$', r'$0$', r'$+1$'])

效果

2.7 Moving spines

Spines are the lines connecting the axis tick marks and noting the
boundaries of the data area. They can be placed at arbitrary positions
and until now, they were on the border of the axis. We’ll change that
since we want to have them in the middle. Since there are four of them
(top/bottom/left/right), we’ll discard the top and right by setting
their color to none and we’ll move the bottom and left ones to
coordinate 0 in data space coordinates.
Spines是连接轴刻度线并区分数据区域边界的线。它们可以放置在任意位置,在此之前,它们都在轴的边界上。现在,我们将它们移到重点来。
由于有四个Spines(上/下/左/右),通过将其颜色设置为none来丢弃顶部和右侧,将在底部和左侧移动到数据空间坐标中的坐标0。

  1. ax = plt.gca() # gca stands for 'get current axis'
  2. ax.spines['right'].set_color('none')
  3. ax.spines['top'].set_color('none')
  4. ax.xaxis.set_ticks_position('bottom')
  5. ax.spines['bottom'].set_position(('data',0))
  6. ax.yaxis.set_ticks_position('left')
  7. ax.spines['left'].set_position(('data',0))

效果

2.8 Adding a legend

  1. plt.plot(X, C, color="blue", linewidth=2.5, linestyle="-", label="cosine")
  2. plt.plot(X, S, color="red", linewidth=2.5, linestyle="-", label="sine")
  3. plt.legend(loc='upper left')

效果

2.9 注释一些点 Annotate some points

Let’s annotate some interesting points using the annotate command. We
chose the 2π/3 value and we want to annotate both the sine and the
cosine. We’ll first draw a marker on the curve as well as a straight
dotted line. Then, we’ll use the annotate command to display some text
with an arrow. 我们使用annotate命令来注释一些有趣的点。我们选择了2π/3值,同时注释正弦和余弦函数。
首先,在曲线上绘制一个标记,同时画一条虚线。然后,我们将使用annotate命令显示一些带箭头的文本。

  1. t = 2 * np.pi / 3
  2. plt.plot([t, t], [0, np.cos(t)], color='blue', linewidth=2.5, linestyle="--")
  3. plt.scatter([t, ], [np.cos(t), ], 50, color='blue')
  4. plt.annotate(r'$cos(\frac{2\pi}{3})=-\frac{1}{2}$',
  5. xy=(t, np.cos(t)), xycoords='data',
  6. xytext=(-90, -50), textcoords='offset points', fontsize=16,
  7. arrowprops=dict(arrowstyle="->", connectionstyle="arc3,rad=.2"))
  8. plt.plot([t, t],[0, np.sin(t)], color='red', linewidth=2.5, linestyle="--")
  9. plt.scatter([t, ],[np.sin(t), ], 50, color='red')
  10. plt.annotate(r'$sin(\frac{2\pi}{3})=\frac{\sqrt{3}}{2}$',
  11. xy=(t, np.sin(t)), xycoords='data',
  12. xytext=(+10, +30), textcoords='offset points', fontsize=16,
  13. arrowprops=dict(arrowstyle="->", connectionstyle="arc3,rad=.2"))

效果

2.10 需要注意的一些细节 Devil is in the details

The tick labels are now hardly visible because of the blue and red
lines. We can make them bigger and we can also adjust their properties
such that they’ll be rendered on a semi-transparent white background.
This will allow us to see both the data and the labels.
由于蓝色和红色线条,刻度标签现在几乎不可见。我们可以让它们更大,我们也可以调整他们的属性,使它们呈现在半透明的白色背景上。这将使我们能够看到数据和标签。

  1. for label in ax.get_xticklabels() + ax.get_yticklabels():
  2. label.set_fontsize(16)
  3. label.set_bbox(dict(facecolor='white', edgecolor='None', alpha=0.65))

此处输入图片的描述


3 Figures, Subplots, Axes and Ticks

A figure in matplotlib means the whole window in the user
interface. Within this figure there can be subplots.

figure是matplotlib呈现在用户面前的整个窗口。figure内的图称为subplots

So far we have used implicit figure and axes creation. This is handy
for fast plots. We can have more control over the display using
figure, subplot, and axes explicitly. While subplot positions the
plots in a regular grid, axes allows free placement within the figure.
Both can be useful depending on your intention. We’ve already worked
with figures and subplots without explicitly calling them. When we
call plot, matplotlib calls gca() to get the current axes and gca in
turn calls gcf() to get the current figure. If there is none it calls
figure() to make one, strictly speaking, to make a subplot(111). Let’s
look at the details.
到目前为止,我们已经使用了隐式图形和轴创建。这对于快速画图很方便。我们可以使用figure,subplots和axes来显式得、更好地控制显示。虽然subplot将图形定位在规则网格中,但axes可以在图中自由放置。两者都可以根据使用者的意愿来放置。
我们已经之前已经接触了figure和subplot,但却没有明确的如此称呼。
当我们调用plot时,matplotlib调用gca()来获取当前axes,gca依次调用gcf()来获取当前figure。
如果没有,那么调用figure()来做一个subplot(111)。让我们来看看细节。

3.1 大图 Figure

Argument Default Description
num 1 number of figure
figsize figure.figsize figure size in inches (width, height)
dpi figure.dpi resolution in dots per inch
facecolor figure.facecolor color of the drawing background
edgecolor figure.edgecolor color of edge around the drawing background
frameon True draw figure frame or not

3.2 子图 subplots

With subplot you can arrange plots in a regular grid. You need to
specify the number of rows and columns and the number of the plot.
Note that the gridspec command is a more powerful alternative.
通过subplot,您可以在普通网格中任意放置图。您需要指定行数和列数以及绘图位置。gridspec命令是一个更强大的替代方案。

3.3 坐标轴 Axes

Axes are very similar to subplots but allow placement of plots at any
location in the figure. So if we want to put a smaller plot inside a
bigger one we do so with axes.
axes非常类似于subplot,但允许将之放置在Figure中的任何位置。所以如果我们想把一个较小的plot放在一个更大的地方,axes也能进行类似的操作。

3.4 刻度 Ticks

Well formatted ticks are an important part of publishing-ready
figures. Matplotlib provides a totally configurable system for ticks.
There are tick locators to specify where ticks should appear and tick
formatters to give ticks the appearance you want. Major and minor
ticks can be located and formatted independently from each other. Per
default minor ticks are not shown, i.e. there is only an empty list
for them because it is as NullLocator (see below).
精确的刻度是出版物的重要组成部分。Matplotlib提供了一个完全可配置ticks的系统。有一些tick定位器可以指定tick应该出现在哪里,并且可以定制ticks的外观。主要和次要刻度可以彼此独立地定位和格式化。每个默认ticks镜像都不会显示,即只有一个空列表,因为它是NullLocator(见下文)。

3.4.1 Tick Locators

Tick locators control the positions of the ticks. They are set as follows:

  1. ax = plt.gca()
  2. ax.xaxis.set_major_locator(eval(locator))

There are several locators for different kind of requirements:

4 其它类型的图 Other Types of Plots

4.1 规则画图 Regular Plots

  1. import numpy as np
  2. import matplotlib.pyplot as plt
  3. n = 256
  4. X = np.linspace(-np.pi, np.pi, n, endpoint=True)
  5. Y = np.sin(2 * X)
  6. plt.axes([0.025, 0.025, 0.95, 0.95])
  7. plt.plot(X, Y + 1, color='blue', alpha=1.00)
  8. plt.fill_between(X, 1, Y + 1, color='blue', alpha=.25)
  9. plt.plot(X, Y - 1, color='blue', alpha=1.00)
  10. plt.fill_between(X, -1, Y - 1, (Y - 1) > -1, color='blue', alpha=.25)
  11. plt.fill_between(X, -1, Y - 1, (Y - 1) < -1, color='red', alpha=.25)
  12. plt.xlim(-np.pi, np.pi)
  13. plt.xticks(())
  14. plt.ylim(-2.5, 2.5)
  15. plt.yticks(())
  16. plt.show()

4.2 散点图 Scatter Plots

  1. import numpy as np
  2. import matplotlib.pyplot as plt
  3. n = 1024
  4. X = np.random.normal(0, 1, n)
  5. Y = np.random.normal(0, 1, n)
  6. T = np.arctan2(Y, X)
  7. plt.axes([0.025, 0.025, 0.95, 0.95])
  8. plt.scatter(X, Y, s=75, c=T, alpha=.5)
  9. plt.xlim(-1.5, 1.5)
  10. plt.xticks(())
  11. plt.ylim(-1.5, 1.5)
  12. plt.yticks(())
  13. plt.show()

4.3 条形图 Bar Plots

  1. import numpy as np
  2. import matplotlib.pyplot as plt
  3. n = 12
  4. X = np.arange(n)
  5. Y1 = (1 - X / float(n)) * np.random.uniform(0.5, 1.0, n)
  6. Y2 = (1 - X / float(n)) * np.random.uniform(0.5, 1.0, n)
  7. plt.axes([0.025, 0.025, 0.95, 0.95])
  8. plt.bar(X, +Y1, facecolor='#9999ff', edgecolor='white')
  9. plt.bar(X, -Y2, facecolor='#ff9999', edgecolor='white')
  10. for x, y in zip(X, Y1):
  11. plt.text(x + 0.4, y + 0.05, '%.2f' % y, ha='center', va= 'bottom')
  12. for x, y in zip(X, Y2):
  13. plt.text(x + 0.4, -y - 0.05, '%.2f' % y, ha='center', va= 'top')
  14. plt.xlim(-.5, n)
  15. plt.xticks(())
  16. plt.ylim(-1.25, 1.25)
  17. plt.yticks(())
  18. plt.show()

4.4 等高线图 Contour Plots

  1. import numpy as np
  2. import matplotlib.pyplot as plt
  3. def f(x,y):
  4. return (1 - x / 2 + x**5 + y**3) * np.exp(-x**2 -y**2)
  5. n = 256
  6. x = np.linspace(-3, 3, n)
  7. y = np.linspace(-3, 3, n)
  8. X,Y = np.meshgrid(x, y)
  9. plt.axes([0.025, 0.025, 0.95, 0.95])
  10. plt.contourf(X, Y, f(X, Y), 8, alpha=.75, cmap=plt.cm.hot)
  11. C = plt.contour(X, Y, f(X, Y), 8, colors='black', linewidth=.5)
  12. plt.clabel(C, inline=1, fontsize=10)
  13. plt.xticks(())
  14. plt.yticks(())
  15. plt.show()

4.5 Imshow

  1. import numpy as np
  2. import matplotlib.pyplot as plt
  3. def f(x, y):
  4. return (1 - x / 2 + x ** 5 + y ** 3 ) * np.exp(-x ** 2 - y ** 2)
  5. n = 10
  6. x = np.linspace(-3, 3, 3.5 * n)
  7. y = np.linspace(-3, 3, 3.0 * n)
  8. X, Y = np.meshgrid(x, y)
  9. Z = f(X, Y)
  10. plt.axes([0.025, 0.025, 0.95, 0.95])
  11. plt.imshow(Z, interpolation='nearest', cmap='bone', origin='lower')
  12. plt.colorbar(shrink=.92)
  13. plt.xticks(())
  14. plt.yticks(())
  15. plt.show()

4.6 饼状图 Pie Charts

  1. import numpy as np
  2. import matplotlib.pyplot as plt
  3. n = 20
  4. Z = np.ones(n)
  5. Z[-1] *= 2
  6. plt.axes([0.025, 0.025, 0.95, 0.95])
  7. plt.pie(Z, explode=Z*.05, colors = ['%f' % (i/float(n)) for i in range(n)])
  8. plt.axis('equal')
  9. plt.xticks(())
  10. plt.yticks()
  11. plt.show()

4.7 场图 Quiver Plots

  1. import numpy as np
  2. import matplotlib.pyplot as plt
  3. n = 8
  4. X, Y = np.mgrid[0:n, 0:n]
  5. T = np.arctan2(Y - n / 2., X - n/2.)
  6. R = 10 + np.sqrt((Y - n / 2.0) ** 2 + (X - n / 2.0) ** 2)
  7. U, V = R * np.cos(T), R * np.sin(T)
  8. plt.axes([0.025, 0.025, 0.95, 0.95])
  9. plt.quiver(X, Y, U, V, R, alpha=.5)
  10. plt.quiver(X, Y, U, V, edgecolor='k', facecolor='None', linewidth=.5)
  11. plt.xlim(-1, n)
  12. plt.xticks(())
  13. plt.ylim(-1, n)
  14. plt.yticks(())
  15. plt.show()

4.8 网格 grids

  1. import matplotlib.pyplot as plt
  2. ax = plt.axes([0.025, 0.025, 0.95, 0.95])
  3. ax.set_xlim(0,4)
  4. ax.set_ylim(0,3)
  5. ax.xaxis.set_major_locator(plt.MultipleLocator(1.0))
  6. ax.xaxis.set_minor_locator(plt.MultipleLocator(0.1))
  7. ax.yaxis.set_major_locator(plt.MultipleLocator(1.0))
  8. ax.yaxis.set_minor_locator(plt.MultipleLocator(0.1))
  9. ax.grid(which='major', axis='x', linewidth=0.75, linestyle='-', color='0.75')
  10. ax.grid(which='minor', axis='x', linewidth=0.25, linestyle='-', color='0.75')
  11. ax.grid(which='major', axis='y', linewidth=0.75, linestyle='-', color='0.75')
  12. ax.grid(which='minor', axis='y', linewidth=0.25, linestyle='-', color='0.75')
  13. ax.set_xticklabels([])
  14. ax.set_yticklabels([])
  15. plt.show()

4.9 多图 Multi Plots

  1. import matplotlib.pyplot as plt
  2. fig = plt.figure()
  3. fig.subplots_adjust(bottom=0.025, left=0.025, top = 0.975, right=0.975)
  4. plt.subplot(2, 1, 1)
  5. plt.xticks(()), plt.yticks(())
  6. plt.subplot(2, 3, 4)
  7. plt.xticks(())
  8. plt.yticks(())
  9. plt.subplot(2, 3, 5)
  10. plt.xticks(())
  11. plt.yticks(())
  12. plt.subplot(2, 3, 6)
  13. plt.xticks(())
  14. plt.yticks(())
  15. plt.show()

4.10 极轴 Polar Axis

  1. import numpy as np
  2. import matplotlib.pyplot as plt
  3. ax = plt.axes([0.025, 0.025, 0.95, 0.95], polar=True)
  4. N = 20
  5. theta = np.arange(0.0, 2 * np.pi, 2 * np.pi / N)
  6. radii = 10 * np.random.rand(N)
  7. width = np.pi / 4 * np.random.rand(N)
  8. bars = plt.bar(theta, radii, width=width, bottom=0.0)
  9. for r,bar in zip(radii, bars):
  10. bar.set_facecolor(plt.cm.jet(r/10.))
  11. bar.set_alpha(0.5)
  12. ax.set_xticklabels([])
  13. ax.set_yticklabels([])
  14. plt.show()

4.11 3D画图 3D Plots

  1. import numpy as np
  2. import matplotlib.pyplot as plt
  3. from mpl_toolkits.mplot3d import Axes3D
  4. fig = plt.figure()
  5. ax = Axes3D(fig)
  6. X = np.arange(-4, 4, 0.25)
  7. Y = np.arange(-4, 4, 0.25)
  8. X, Y = np.meshgrid(X, Y)
  9. R = np.sqrt(X ** 2 + Y ** 2)
  10. Z = np.sin(R)
  11. ax.plot_surface(X, Y, Z, rstride=1, cstride=1, cmap=plt.cm.hot)
  12. ax.contourf(X, Y, Z, zdir='z', offset=-2, cmap=plt.cm.hot)
  13. ax.set_zlim(-2, 2)
  14. plt.show()

4.12 文本 text

  1. import numpy as np
  2. import matplotlib.pyplot as plt
  3. eqs = []
  4. eqs.append((r"$W^{3\beta}_{\delta_1 \rho_1 \sigma_2} = U^{3\beta}_{\delta_1 \rho_1} + \frac{1}{8 \pi 2} \int^{\alpha_2}_{\alpha_2} d \alpha^\prime_2 \left[\frac{ U^{2\beta}_{\delta_1 \rho_1} - \alpha^\prime_2U^{1\beta}_{\rho_1 \sigma_2} }{U^{0\beta}_{\rho_1 \sigma_2}}\right]$"))
  5. eqs.append((r"$\frac{d\rho}{d t} + \rho \vec{v}\cdot\nabla\vec{v} = -\nabla p + \mu\nabla^2 \vec{v} + \rho \vec{g}$"))
  6. eqs.append((r"$\int_{-\infty}^\infty e^{-x^2}dx=\sqrt{\pi}$"))
  7. eqs.append((r"$E = mc^2 = \sqrt{{m_0}^2c^4 + p^2c^2}$"))
  8. eqs.append((r"$F_G = G\frac{m_1m_2}{r^2}$"))
  9. plt.axes([0.025, 0.025, 0.95, 0.95])
  10. for i in range(24):
  11. index = np.random.randint(0, len(eqs))
  12. eq = eqs[index]
  13. size = np.random.uniform(12, 32)
  14. x,y = np.random.uniform(0, 1, 2)
  15. alpha = np.random.uniform(0.25, .75)
  16. plt.text(x, y, eq, ha='center', va='center', color="#11557c", alpha=alpha,
  17. transform=plt.gca().transAxes, fontsize=size, clip_on=True)
  18. plt.xticks(())
  19. plt.yticks(())
  20. plt.show()

5 本教程之外 Beyond this tutorial

5.1 其余教程

Pyplot tutorial
Artist tutorial
Image tutorial
Path Tutorial
Transformations Tutorial
Working with text

5.2 Matplotlib文档

User Guide

5.3 代码文档

help(plt.XXX)

5.4 Galleries

Galleries 帮助您实现已有图形。

5.5 Mailing lists

Uesr mailing lists
developers mailing lists


6 快速参考

6.1 线条属性 Line Properties

Property Description Appearance
alpha (or a) 透明度 0-1
antialiased True or False - 使用antialised渲染
color (or c) matplotlib color arg
linestyle (or ls) see Line properties
linewidth (or lw) float, the line width in points
solid_capstyle Cap style for solid lines
solid_joinstyle Join style for solid lines
dash_capstyle Cap style for dashes
dash_joinstyle Join style for dashes
marker see Markers
markeredgewidth (mew) line width around the marker symbol
markeredgecolor (mec) edge color if a marker is used
markerfacecolor (mfc) face color if a marker is used
markersize (ms) size of the marker in points

6.2 线条风格 Line Styles

Line Styles

6.3 标记 Marks

Marks

6.4 颜色表 ColorMaps

此处输入图片的描述


心血来潮,自娱自乐,供自己参考=.=
mr.yxj@foxmail.com

添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注