Task 02:艺术画笔见乾坤


前言

在学习了matplotlib的基础之后,本节我们学习利用matplotlib画出更加复杂的图形,并了解其中的原理,依次介绍了matplotlib的三层api,它的基本元素及对象容器。


一、概述

1.matplotlib的三层api

matplotlib的原理用Artist对象在画布(canvas)上绘制(Render)图形。
与人画画的步骤类似:

  1. 准备一块画布或画纸
  2. 准备好颜料、画笔等制图工具
  3. 作画

所以matplotlib有三个层次的API:
matplotlib.backend_bases.FigureCanvas 代表了绘图区,所有的图像都是在绘图区完成的 ;
matplotlib.backend_bases.Renderer 代表了渲染器,可以近似理解为画笔,控制如何在 FigureCanvas上画图 ;
matplotlib.artist.Artist 代表了具体的图表组件,即调用了Renderer的接口在Canvas上作图。
前两者处理程序和计算机的底层交互事项,第三项Artist就是具体的调用接口来做出我们想要的图,比如图形、文本、线条的设定。所以通常来说,我们95%的时间都是用来和matplotlib.artist.Artist类打交道的。

2.Artist的分类

Artist有两种类型:primitives 和containers。
primitive是基本要素,它包含一些我们要在绘图区作图用到的标准图形对象,如曲线Line2D,文字text,矩形 Rectangle,图像image等。
container是容器,用来装基本要素的地方,包括**图形figure、坐标系Axes和坐标轴Axis。**它们之间的关系如下图所示:
在这里插入图片描述

3. matplotlib的标准用法

matplotlib的标准使用流程为:

  1. 创建一个Figure实例
  2. 使用Figure实例创建一个或者多个Axes或Subplot实例
  3. 使用Axes实例的辅助方法来创建primitive(Axes是一种容器,它可能是matplotlib API中最重要的类)

示例:

import matplotlib.pyplot as plt 
import numpy as np 
# step 1 # 我们用 matplotlib.pyplot.figure() 创建了一个Figure实例 
fig = plt.figure() 
# step 2 # 然后用Figure实例创建了一个两行一列(即可以有两个subplot)的绘图区,并同时在第一个位置创建了一个 subplot 
ax = fig.add_subplot(2, 1, 1) # two rows, one column, first plot 
# step 3 # 然后用Axes实例的方法画了一条曲线 
t = np.arange(0.0, 1.0, 0.01) 
s = np.sin(2*np.pi*t) 
line, = ax.plot(t, s, color='blue', lw=2)

在这里插入图片描述

二、基本元素 - primitives

各容器中可能会包含多种基本要素-primitives,primitives 的几种常用类型:曲线-Line2D,矩形-Rectangle,图像-image。

1. 2DLines

matplotlib中线-line的含义:它表示的可以是连接所有顶点的实线样式,也可以是每个顶点的标记。
它的构造函数为:

class matplotlib.lines.Line2D(xdata, ydata, linewidth=None, linestyle=None, color=None,marker=None, markersize=None, markeredgewidth=None, markeredgecolor=None,
markerfacecolor=None, markerfacecoloralt='none', fillstyle=None, antialiased=None,
dash_capstyle=None, solid_capstyle=None, dash_joinstyle=None, solid_joinstyle=None,
pickradius=5, drawstyle=None, markevery=None, **kwargs)

常用参数:
xdata:需要绘制的line中,点在x轴上的取值,若忽略,则默认为range(1,len(ydata)+1);
ydata:需要绘制的line中,点在y轴上的取值;
linewidth:线条宽度;
linestyle:线型;
color:线条颜色;
marker:点的标记;
markersize:标记的size。

a. 如何设置Line2D的属性

三种方法:

  1. 直接在plot()函数中设置 ;
  2. 通过获得线对象,对线对象进行设置 ;
  3. 获得线属性,使用setp()函数设置。
# 1) 直接在plot()函数中设置 
import matplotlib.pyplot as plt 
x = range(0,5) 
y = [2,5,7,8,10] 
plt.plot(x,y, linewidth=10); # 设置线的粗细参数为10

在这里插入图片描述

# 2) 通过获得线对象,对线对象进行设置 
x = range(0,5) 
y = [2,5,7,8,10] 
line, = plt.plot(x, y, '-') 
line.set_antialiased(False) # 关闭抗锯齿功能

在这里插入图片描述

# 3) 获得线属性,使用setp()函数设置 
x = range(0,5) 
y = [2,5,7,8,10] 
lines = plt.plot(x, y) 
plt.setp(lines, color='r', linewidth=10);

在这里插入图片描述

b. 如何绘制lines

1. 绘制直线line
1) pyplot方法绘制

# 1. pyplot方法绘制 
import matplotlib.pyplot as plt 
x = range(0,5) 
y = [2,5,7,8,10] 
plt.plot(x,y);

在这里插入图片描述
2) Line2D对象绘制

# 2. Line2D对象绘制 
import matplotlib.pyplot as plt 
from matplotlib.lines import Line2D 
fig = plt.figure() 
ax = fig.add_subplot(111) 
line = Line2D(x, y) 
ax.add_line(line) 
ax.set_xlim(min(x), max(x)) 
ax.set_ylim(min(y), max(y)) 
plt.show()

在这里插入图片描述

2. errorbar绘制误差折线图
pyplot通过errorbar类绘制误差折线图,它的构造函数为:

matplotlib.pyplot.errorbar(x, y, yerr=None, xerr=None, fmt='', ecolor=None, elinewidth=None,capsize=None, barsabove=False, lolims=False, uplims=False, xlolims=False, xuplims=False,errorevery=1, capthick=None, *, data=None, **kwargs)

主要参数:
x:需要绘制的line中的点在x轴上的取值;
y:需要绘制的line中的点在y轴上的取值;
yerr:指定y轴的水平误差;
xerr:指定x轴的水平误差;
fmt:指定折线图中某个点的颜色,形状,线条风格,例如‘co–’;
ecolor:指定error bar的颜色;
elinewidth:指定error bar的线条宽度。

import numpy as np 
import matplotlib.pyplot as plt 
fig = plt.figure() 
x = np.arange(10) 
y = 2.5 * np.sin(x / 20 * np.pi) 
yerr = np.linspace(0.05, 0.2, 10) 
plt.errorbar(x, y + 3, yerr=yerr, label='both limits (default)');

在这里插入图片描述

2. patches

matplotlib.patches.Patch类是二维图形类。它的基类是matplotlib.artist.Artist,它的构造函数为:

Patch(edgecolor=None, facecolor=None, color=None, linewidth=None, linestyle=None,
antialiased=None, hatch=None, fill=True, capstyle=None, joinstyle=None, **kwargs)

a. Rectangle-矩形

定义:通过锚点xy及其宽度和高度生成。xy控制锚点,width和height分别控制宽和高。它的构造函数为:

class matplotlib.patches.Rectangle(xy, width, height, angle=0.0, **kwargs)

在实际中最常见的矩形图是hist直方图和bar条形图
1.hist-直方图

matplotlib.pyplot.hist(x,bins=None,range=None, density=None, bottom=None, histtype='bar',align='mid', log=False, color=None, label=None, stacked=False, normed=None)

常用参数:
x: 数据集,最终的直方图将对数据集进行统计;
bins: 统计的区间分布;
range: tuple, 显示的区间,range在没有给出bins时生效;
density: bool,默认为false,显示的是频数统计结果,为True则显示频率统计结果,这里需要注意,频率统计结果=区间数目/(总数*区间宽度),和normed效果一致,官方推荐使用density;
histtype: 可选{‘bar’, ‘barstacked’, ‘step’, ‘stepfilled’}之一,默认为bar,推荐使用默认配置,step使用的是梯状,stepfilled则会对梯状内部进行填充,效果与bar类似;
align: 可选{‘left’, ‘mid’, ‘right’}之一,默认为’mid’,控制柱状图的水平分布,left或者right,会有部分空白区域,推荐使用默认;
log: bool,默认为False,即y坐标轴是否选择指数刻度;
stacked: bool,默认为False,是否为堆积状图。

1)hist绘制直方图

import matplotlib.pyplot as plt 
import numpy as np 
x=np.random.randint(0,100,100) #生成[0-100)之间的100个数据,即数据集 
bins=np.arange(0,101,10) 
#设置连续的边界值,即直方图的分布区间[0,10),[10,20)... 
plt.hist(x,bins,color='fuchsia',alpha=0.8)#alpha设置透明度,0为完全透明 
plt.xlabel('scores') 
plt.ylabel('count') 
plt.xlim(0,100)#设置x轴分布范围 
plt.show()

在这里插入图片描述
2)Rectangle矩形类绘制直方图

import pandas as pd 
import re 
df = pd.DataFrame(columns = ['data']) 
df.loc[:,'data'] = x 
df['fenzu'] = pd.cut(df['data'], bins=bins, right = False,include_lowest=True) 
df_cnt = df['fenzu'].value_counts().reset_index() 
df_cnt.loc[:,'mini'] = df_cnt['index'].astype(str).map(lambda x:re.findall('\[(.*)\,',x) [0]).astype(int) 
df_cnt.loc[:,'maxi'] = df_cnt['index'].astype(str).map(lambda x:re.findall('\,(.*)\)',x) [0]).astype(int) 
df_cnt.loc[:,'width'] = df_cnt['maxi']- df_cnt['mini'] 
df_cnt.sort_values('mini',ascending = True,inplace = True) 
df_cnt.reset_index(inplace = True,drop = True) 

#用Rectangle把hist绘制出来 
import matplotlib.pyplot as plt 
fig = plt.figure() 
ax1 = fig.add_subplot(111) 
for i in df_cnt.index: 
    rect = plt.Rectangle((df_cnt.loc[i,'mini'],0),df_cnt.loc[i,'width'],df_cnt.loc[i,'fenzu']) 
    ax1.add_patch(rect) 
ax1.set_xlim(0, 100) 
ax1.set_ylim(0, 16) 
plt.show()

在这里插入图片描述
2.bar-柱状图

matplotlib.pyplot.bar(left, height, alpha=1, width=0.8, color=, edgecolor=, label=, lw=3)

常用参数:
left:x轴的位置序列,一般采用range函数产生一个序列,但是有时候可以是字符串;
height:y轴的数值序列,即柱形图的高度,一般就是我们需要展示的数据;
alpha:透明度,值越小越透明;
width:柱形图的宽度,一般设为0.8;
color或facecolor:柱形图填充颜色;
edgecolor:图形边缘颜色;
label:解释每个图像代表的含义,这个参数是为legend()函数做铺垫的,表示该bar的标签。

1)bar绘制柱状图

# bar绘制柱状图 
import matplotlib.pyplot as plt 
y = range(1,17) 
plt.bar(np.arange(16), y, alpha=0.5, width=0.5, color='yellow', edgecolor='red', label='The First Bar', lw=3);

在这里插入图片描述

2)Rectangle矩形类绘制柱状图

# Rectangle矩形类绘制柱状图 
#import matplotlib.pyplot as plt 
fig = plt.figure() 
ax1 = fig.add_subplot(111) 
for i in range(1,17): 
    rect = plt.Rectangle((i+0.25,0),0.5,i) 
    ax1.add_patch(rect) 
ax1.set_xlim(0, 16) 
ax1.set_ylim(0, 16) 
plt.show()

在这里插入图片描述

b. Polygon-多边形

matplotlib.patches.Polygon类是多边形类。其基类是matplotlib.patches.Patch,它的构造函数为:

class matplotlib.patches.Polygon(xy, closed=True, **kwargs)

xy是一个N×2的numpy array,为多边形的顶点。
closed为True则指定多边形将起点和终点重合从而显式关闭多边形。

matplotlib.patches.Polygon类中常用的是fill类,它是基于xy绘制一个填充的多边形,它的定义:

matplotlib.pyplot.fill(*args, data=None, **kwargs)
# 用fill来绘制图形 
import matplotlib.pyplot as plt 
x = np.linspace(0, 5 * np.pi, 1000) 
y1 = np.sin(x) 
y2 = np.sin(2 * x) 
plt.fill(x, y1, color = "g", alpha = 0.3);

在这里插入图片描述


c. Wedge-契形

matplotlib.patches.Polygon类是多边形类。其基类是matplotlib.patches.Patch,它的构造函数为:

class matplotlib.patches.Wedge(center, r, theta1, theta2, width=None, **kwargs)

一个Wedge-契形是以坐标x,y为中心,半径为r,从θ1扫到θ2(单位是度)。
如果宽度给定,则从内半径r-宽度到外半径r画出部分楔形。

wedge中比较常见的是绘制饼状图。
matplotlib.pyplot.pie语法:

matplotlib.pyplot.pie(x, explode=None, labels=None, colors=None, autopct=None, pctdistance=0.6,
shadow=False, labeldistance=1.1, startangle=0, radius=1, counterclock=True, wedgeprops=None,
textprops=None, center=0, 0, frame=False, rotatelabels=False, *, normalize=None, data=None)

制作数据x的饼图,每个楔子的面积用x/sum(x)表示。
主要参数:
x:契型的形状,一维数组。
explode:如果不是等于None,则是一个len(x)数组,它指定用于偏移每个楔形块的半径的分数。
labels:用于指定每个契型块的标记,取值是列表或为None。
colors:饼图循环使用的颜色序列。如果取值为None,将使用当前活动循环中的颜色。
startangle:饼状图开始的绘制的角度。

1.pie绘制饼状图

import matplotlib.pyplot as plt 
labels = 'Frogs', 'Hogs', 'Dogs', 'Logs' 
sizes = [15, 30, 45, 10] 
explode = (0, 0.1, 0, 0) 
fig1, ax1 = plt.subplots() 
ax1.pie(sizes, explode=explode, labels=labels, autopct='%1.1f%%', shadow=True, startangle=90) 
ax1.axis('equal') # Equal aspect ratio ensures that pie is drawn as a circle. 
plt.show()

在这里插入图片描述
2.wedge绘制饼图

import matplotlib.pyplot as plt 
from matplotlib.patches import Circle, Wedge 
from matplotlib.collections import PatchCollection 
fig = plt.figure() 
ax1 = fig.add_subplot(111) 
theta1 = 0 
sizes = [15, 30, 45, 10] 
patches = [] 
patches += [ Wedge((0.3, 0.3), .2, 0, 54), # Full circle 
            Wedge((0.3, 0.3), .2, 54, 162), # Full ring \
            Wedge((0.3, 0.3), .2, 162, 324), # Full sector 
            Wedge((0.3, 0.3), .2, 324, 360), # Ring sector 
           ]
            
colors=100 * np.random.rand(len(patches)) 
p=PatchCollection(patches, alpha=0.4) 
p.set_array(colors) 
ax1.add_collection(p) 
plt.show()

在这里插入图片描述

3.collections

collections类是用来绘制一组对象的集合,collections有许多不同的子类,如RegularPolyCollection,CircleCollection, Pathcollection, 分别对应不同的集合子类型。其中比较常用的就是散点图,它是属于PathCollection子类,scatter方法提供了该类的封装,根据x与y绘制不同大小或颜色标记的散点图。 它的构造方法为:

Axes.scatter(self, x, y, s=None, c=None, marker=None, cmap=None, norm=None, vmin=None,
vmax=None, alpha=None, linewidths=None, verts=, edgecolors=None, *, plotnonfinite=False,
data=None, **kwargs)

主要参数:
x:数据点x轴的位置;
y:数据点y轴的位置;
s:尺寸大小;
c:可以是单个颜色格式的字符串,也可以是一系列颜色;
marker: 标记的类型。

#用scatter绘制散点图 
x = [0,2,4,6,8,10] 
y = [10]*len(x) 
s = [20*2**n for n in range(len(x))] 
plt.scatter(x,y,s=s) 
plt.show()

在这里插入图片描述

4. images

images是matplotlib中绘制image图像的类,其中最常用的imshow可以根据数组绘制成图像,它的构造函数为:

class matplotlib.image.AxesImage(ax, cmap=None, norm=None, interpolation=None, origin=None,
extent=None, filternorm=True, filterrad=4.0, resample=False, **kwargs)

imshow根据数组绘制图像:

matplotlib.pyplot.imshow(X, cmap=None, norm=None, aspect=None, interpolation=None,
alpha=None, vmin=None, vmax=None, origin=None, extent=None, shape=, filternorm=1,
filterrad=4.0, imlim=, resample=None, url=None, *, data=None, **kwargs)

使用imshow画图时首先需要传入一个数组,数组对应的是空间内像素位置和像素点的值,interpolation参数可以设置不同的差值方法,具体效果如下。

import matplotlib.pyplot as plt 
import numpy as np 
methods = [None, 'none', 'nearest', 'bilinear', 'bicubic', 'spline16', 'spline36', 'hanning', 'hamming', 'hermite', 'kaiser', 'quadric', 'catrom', 'gaussian', 'bessel', 'mitchell', 'sinc', 'lanczos'] 
grid = np.random.rand(4, 4) 
fig, axs = plt.subplots(nrows=3, ncols=6, figsize=(9, 6), subplot_kw={'xticks': [], 'yticks': []}) 
for ax, interp_method in zip(axs.flat, methods): 
    ax.imshow(grid, interpolation=interp_method, cmap='viridis') 
    ax.set_title(str(interp_method)) 
plt.tight_layout() 
plt.show()

在这里插入图片描述

三、对象容器 - Object container

容器会包含一些primitives,和它自身的属性。比如Axes Artist,它是一种容器,它包含了很多primitives,比如Line2D,Text;同时,它也有自身的属性,比如xscal,用来控制X轴是linear还是log的。

1. Figure容器

matplotlib.figure.Figure是Artist最顶层的container-对象容器,它包含了图表中的所有元素。一张图表的背景就是在Figure.patch中的一个矩形Rectangle。
当我们向图表添加Figure.add_subplot()或者Figure.add_axes()元素时,这些都会被添加到Figure.axes列表中。

fig = plt.figure() 
ax1 = fig.add_subplot(211) # 作一幅2*1的图,选择第1个子图 
ax2 = fig.add_axes([0.1, 0.1, 0.7, 0.3]) # 位置参数,四个数分别代表了(left,bottom,width,height) 
print(ax1) 
print(fig.axes) # fig.axes 中包含了subplot和axes两个实例, 刚刚添加的

在这里插入图片描述
由于Figure维持了current axes,因此不能手动的从Figure.axes列表中添加删除元素,而要通过Figure.add_subplot()、Figure.add_axes()来添加元素通过Figure.delaxes()来删除元素。但是你可以迭代或者访问Figure.axes中的Axes,然后修改它的属性。

比如遍历axes里的内容,并且添加网格线

fig = plt.figure() 
ax1 = fig.add_subplot(211) 
for ax in fig.axes: 
    ax.grid(True)

在这里插入图片描述

Figure也有它自己的text、line、patch、image。你可以直接通过add primitive语句直接添加。但要注意Figure默认的坐标系是以像素为单位,你可能需要转换成figure坐标系:(0,0)表示左下点,(1,1)表示右上点。

Figure容器的常见属性
Figure.patch属性:Figure的背景矩形;
Figure.axes属性:一个Axes实例的列表(包括Subplot);
Figure.images属性:一个FigureImages patch列表;
Figure.lines属性:一个Line2D实例的列表(很少使用);
Figure.legends属性:一个Figure Legend实例列表(不同于Axes.legends);
Figure.texts属性:一个Figure Text实例列表。

2. Axes容器

matplotlib.axes.Axes是matplotlib的核心。大量的用于绘图的Artist存放在它的内部,并且它有许多辅助方法来创建和添加Artist给它自己,而且它也有许多赋值方法来访问和修改这些Artist。
和Figure容器类似,Axes包含了一个patch属性,对于笛卡尔坐标系而言,它是一个Rectangle;对于极坐标而言,它是一个Circle。这个patch属性决定了绘图区域的形状、背景和边框。

import numpy as np 
import matplotlib.pyplot as plt 
import matplotlib 
fig = plt.figure() 
ax = fig.add_subplot(111) 
rect = ax.patch # axes的patch是一个Rectangle实例 
rect.set_facecolor('green')

在这里插入图片描述

3. Axis容器

matplotlib.axis.Axis实例处理tick line、grid line、tick label以及axis label的绘制,它包括坐标轴上的刻度线、刻度label等。通常你可以独立的配置y轴的左边以及右边的刻度,也可以独立地配置x轴的上边以及下边的刻度。
刻度包括主刻度和次刻度,它们都是Tick刻度对象
Axis也存储了用于自适应,平移以及缩放的data_interval和view_interval。
它还有Locator实例和Formatter实例用于控制刻度线的位置以及刻度label。
每个Axis都有一个label属性,也有主刻度列表和次刻度列表。这些ticks是axis.XTick和axis.YTick实例,它们包含line primitive以及text primitive用来渲染刻度线以及刻度文本。
刻度是动态创建的,只有在需要创建的时候才创建(比如缩放的时候)。
Axis也提供了一些辅助方法来获取刻度文本、刻度线位置等等:
常见的如下:

# 不用print,直接显示结果 
from IPython.core.interactiveshell import InteractiveShell 
InteractiveShell.ast_node_interactivity = "all" 
fig, ax = plt.subplots() 
x = range(0,5) 
y = [2,5,7,8,10] 
plt.plot(x, y, '-') 
axis = ax.xaxis # axis为X轴对象 
axis.get_ticklocs() # 获取刻度线位置 
axis.get_ticklabels() # 获取刻度label列表(一个Text实例的列表)。 可以通过minor=True|False关键字 参数控制输出minor还是major的tick label。 
axis.get_ticklines() # 获取刻度线列表(一个Line2D实例的列表)。 可以通过minor=True|False关键字参 数控制输出minor还是major的tick line。 
axis.get_data_interval()# 获取轴刻度间隔 
axis.get_view_interval()# 获取轴视角(位置)的间隔

在这里插入图片描述
调整一些轴和刻度的属性:

fig = plt.figure() # 创建一个新图表 
rect = fig.patch # 矩形实例并将其设为黄色 
rect.set_facecolor('lightgoldenrodyellow') 
ax1 = fig.add_axes([0.1, 0.3, 0.4, 0.4]) # 创一个axes对象,从(0.1,0.3)的位置开始,宽和高都为0.4, 
rect = ax1.patch # ax1的矩形设为灰色 
rect.set_facecolor('lightslategray') 
for label in ax1.xaxis.get_ticklabels(): # 调用x轴刻度标签实例,是一个text实例 
    label.set_color('red') # 颜色 
    label.set_rotation(45) # 旋转角度 
    label.set_fontsize(16) # 字体大小 
for line in ax1.yaxis.get_ticklines(): # 调用y轴刻度线条实例, 是一个Line2D实例 
    line.set_color('green') # 颜色 
    line.set_markersize(25) # marker大小 
    line.set_markeredgewidth(2)# marker粗细 
plt.show()

在这里插入图片描述

4. Tick容器

matplotlib.axis.Tick是从Figure到Axes到Axis到Tick中最末端的容器对象
Tick包含了tick、grid line实例以及对应的label。
所有的这些都可以通过Tick的属性获取,常见的tick属性有
Tick.tick1line:Line2D实例
Tick.tick2line:Line2D实例
Tick.gridline:Line2D实例
Tick.label1:Text实例
Tick.label2:Text实例

y轴分为左右两个,因此tick1对应左侧的轴;tick2对应右侧的轴。
x轴分为上下两个,因此tick1对应下侧的轴;tick2对应上侧的轴。

例:将Y轴右侧轴设为主轴,并将标签设置为美元符号且为绿色:

import numpy as np 
import matplotlib.pyplot as plt 
import matplotlib 
fig, ax = plt.subplots() 
ax.plot(100*np.random.rand(20)) # 设置ticker的显示格式 
formatter = matplotlib.ticker.FormatStrFormatter('$%1.2f') 
ax.yaxis.set_major_formatter(formatter) # 设置ticker的参数,右侧为主轴,颜色为绿色 
ax.yaxis.set_tick_params(which='major', labelcolor='green', labelleft=False, labelright=True);

在这里插入图片描述

总结

以上就是今天要讲的内容,主要介绍了matplotlib的三种api,以及通过api画出各种各样的图形的具体方法。

参考资料

[1].https://zhuanlan.zhihu.com/p/32693665
[2].https://matplotlib.org/stable/api/artist_api.html
[3].https://matplotlib.org/stable/tutorials/intermediate/artists.html
[4].https://www.bookstack.cn/read/huaxiaozhuan-ai/spilt.2.333f5abdbabf383d.md

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Never give up

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值