­

pyecharts原來可以這樣快速入門

  • 2020 年 2 月 21 日
  • 筆記

最近兩天,翻看下pyecharts的源碼,感嘆這個框架寫的真棒,思路清晰,設計簡潔,通俗易懂,推薦讀者們有空也閱讀下。

bee君是被pyecharts官檔介紹-五個特性所吸引:

1)簡潔的 API 設計,使用如絲滑般流暢,支援鏈式調用;

2)囊括了 30+ 種常見圖表,應有盡有;

3)支援主流 Notebook 環境,Jupyter Notebook 和 JupyterLab;

4)可輕鬆集成至 Flask,Django 等主流 Web 框架;

5)高度靈活的配置項,可輕鬆搭配出精美的圖表

pyecharts確實也如上面五個特性介紹那樣,使用起來非常方便。那麼,有些讀者不禁好奇會問,pyecharts是如何做到的?

我們不妨從pyecharts官檔5分鐘入門pyecharts章節開始,由表(最高層函數)及里(底層函數也就是所謂的源碼),一探究竟。

第一個例子

不妨從官檔給出的第一個例子說起,

from pyecharts.charts import Bar    bar = Bar()  bar.add_xaxis(["襯衫", "羊毛衫", "雪紡衫", "褲子", "高跟鞋", "襪子"])  bar.add_yaxis("商家A", [5, 20, 36, 10, 75, 90])  # render 會生成本地 HTML 文件,默認會在當前目錄生成 render.html 文件  # 也可以傳入路徑參數,如 bar.render("mycharts.html")  bar.render()

第一行程式碼:from pyecharts.charts import Bar,先上一張源碼中包的結構圖

圖1

bar.py模組中定義了類Bar(RectChart),如下所示:

class Bar(RectChart):      """      <<< Bar Chart >>>        Bar chart presents categorical data with rectangular bars      with heights or lengths proportional to the values that they represent.      """

這裡有讀者可能會有以下兩個問題:

1)為什麼根據圖1中的包結構,為什麼不這麼寫:from pyecharts.charts.basic_charts import Bar

圖2

答:請看圖2中__init__.py模組,文件內容如下,看到導入charts包,而非charts.basic_charts

from pyecharts import charts, commons, components, datasets, options, render, scaffold  from pyecharts._version import __author__, __version__

2)Bar(RectChart)是什麼意思

答:RectChart是Bar的子類

下面4行程式碼,很好理解,沒有特殊性。

第一個例子的改寫

pyecharts主要兩個大版本,0.5基版本和1.0基版本,從1.0基版本開始全面支援鏈式調用,bee君也很喜愛這種鏈式調用模式,程式碼看起來更加緊湊:

from pyecharts.charts import Bar    bar = (      Bar()      .add_xaxis(["襯衫", "羊毛衫", "雪紡衫", "褲子", "高跟鞋", "襪子"])      .add_yaxis("商家A", [5, 20, 36, 10, 75, 90])  )  bar.render()

實現鏈式調用也沒有多難,保證返回類本身self即可,如果非要有其他返回對象,那麼要提到類內以便被全局共享,

add_xaxis函數返回self

    def add_xaxis(self, xaxis_data: Sequence):          self.options["xAxis"][0].update(data=xaxis_data)          self._xaxis_data = xaxis_data          return self

add_yaxis函數同樣返回self.

一切皆options

pyecharts用起來很爽的另一個重要原因,參數配置項封裝的非常nice,通過定義一些列基礎的配置組件,比如global_options.py模組中定義的配置對象有以下27

    AngleAxisItem,      AngleAxisOpts,      AnimationOpts,      Axis3DOpts,      AxisLineOpts,      AxisOpts,      AxisPointerOpts,      AxisTickOpts,      BrushOpts,      CalendarOpts,      DataZoomOpts,      Grid3DOpts,      GridOpts,      InitOpts,      LegendOpts,      ParallelAxisOpts,      ParallelOpts,      PolarOpts,      RadarIndicatorItem,      RadiusAxisItem,      RadiusAxisOpts,      SingleAxisOpts,      TitleOpts,      ToolBoxFeatureOpts,      ToolboxOpts,      TooltipOpts,      VisualMapOpts,

第二個例子

了解上面的配置對象後,再看官檔給出的第二個例子,與第一個例子相比,增加了一行程式碼:set_global_opts函數

from pyecharts.charts import Bar  from pyecharts import options as opts    # V1 版本開始支援鏈式調用  # 你所看到的格式其實是 `black` 格式化以後的效果  # 可以執行 `pip install black` 下載使用  bar = (      Bar()      .add_xaxis(["襯衫", "羊毛衫", "雪紡衫", "褲子", "高跟鞋", "襪子"])      .add_yaxis("商家A", [5, 20, 36, 10, 75, 90])      .set_global_opts(title_opts=opts.TitleOpts(title="主標題", subtitle="副標題"))    bar.render()

set_global_opts函數在pyecharts中被高頻使用,它定義在底層基礎模組Chart.py中,它是前面說到的RectChart的子類,Bar類的孫子類。

瀏覽下這個函數的參數

def set_global_opts(          self,          title_opts: types.Title = opts.TitleOpts(),          legend_opts: types.Legend = opts.LegendOpts(),          tooltip_opts: types.Tooltip = None,          toolbox_opts: types.Toolbox = None,          brush_opts: types.Brush = None,          xaxis_opts: types.Axis = None,          yaxis_opts: types.Axis = None,          visualmap_opts: types.VisualMap = None,          datazoom_opts: types.DataZoom = None,          graphic_opts: types.Graphic = None,          axispointer_opts: types.AxisPointer = None,      ):

以第二個參數title_opts為例,說明pyecharts中參數賦值的風格。

首先,title_opts默認參數,默認值為opts.TitleOpts(),這個對象在上一節中,我們提到過,是global_options.py模組中定義的27個配置對象種的一個。

其次,pyecharts中為了增強程式碼可讀性,參數的類型都顯示的給出。此處它的類型為:types.Title. 這是什麼類型?它的類型不是TitleOpts嗎?不急,看看Title這個類型的定義:

Title = Union[opts.TitleOpts, dict]

原來Title可能是opts.TitleOpts, 也可能是python原生的dict. 通過Union實現的就是這種類型效果。所以這就解釋了官檔中為什麼說也可以使用字典配置參數的問題,如下官檔:

    # 或者直接使用字典參數      # .set_global_opts(title_opts={"text": "主標題", "subtext": "副標題"})  )

最後,真正的關於圖表的標題相關的屬性都被封裝到TitleOpts類中,比如title,subtitle屬性,查看源碼,TitleOpts對象還有更多屬性:

class TitleOpts(BasicOpts):      def __init__(          self,          title: Optional[str] = None,          title_link: Optional[str] = None,          title_target: Optional[str] = None,          subtitle: Optional[str] = None,          subtitle_link: Optional[str] = None,          subtitle_target: Optional[str] = None,          pos_left: Optional[str] = None,          pos_right: Optional[str] = None,          pos_top: Optional[str] = None,          pos_bottom: Optional[str] = None,          padding: Union[Sequence, Numeric] = 5,          item_gap: Numeric = 10,          title_textstyle_opts: Union[TextStyleOpts, dict, None] = None,          subtitle_textstyle_opts: Union[TextStyleOpts, dict, None] = None,      ):

小結

OK. 到此跟隨5分鐘入門的官檔,結合兩個例子實現的背後源碼,探討了:

1)與包結構組織相關的__init__.py;2)類的繼承關係:Bar->RectChart->Chart;3)鏈式調用;4)重要的參數配置包options,以TitleOpts類為例,set_global_opts將它裝載到Bar類中實現屬性自定義。