メインコンテンツへスキップ

Pythonのクラス図をPyreverseで自動生成する

·2149 文字·5 分
目次

はじめに
#

Pythonで作成したコードのクラス図を、Pyreverseを使って自動生成する方法を解説します。クラス図とは、クラスの属性やメソッド、およびクラス間の関係を示す以下のような図のことです。

継承のクラス図
継承のクラス図

この記事で検証した環境は以下の通りです。

  • OS: Windows 10 Home
  • Python 3.11.6
  • Pylint 3.0.2
  • Graphviz(Pythonライブラリ) 0.20.1
  • Graphviz(本体) 2.46.1

PyreverseはPylintというライブラリに含まれています。また、Graphvizはクラス図を画像として出力するために必要であり、Windows用のソフト本体と、Pythonのインターフェースとしてのライブラリの両方をインストールします。

この記事はPython Advent Calendar 2023 (Qiita) 13日目の記事です。

インストール
#

Pythonは既にインストールされていることを前提とします。以下のコマンドを実行して、Pylint(Pyreverseも含まれています)とGraphviz(Pythonライブラリ)をインストールします。

> pip install pylint
> pip install graphviz

次に、Graphvizの公式サイトからインストーラを入手して、Graphvizの本体をインストールします。 https://graphviz.org/download/

インストール中にパスを通すか聞かれるので、通しておきます。以下の画面で"Add Graphviz to the system PATH for all users"または"current user"を選択します。

Graphvizのインストール画面
Graphvizのインストール画面

Graphvizのインストール後、PowerShellまたはコマンドプロンプトで以下のコマンドを実行します。Graphvizにパスが通っていれば、バージョン番号が表示されます。

> dot -V
dot - graphviz version 2.46.0 (20210118.1747)

クラス図の作成例
#

まず、クラスが1つだけのPythonスクリプトを例に、Pyreverseを使ってクラス図を出力します。以下のスクリプトでは、Personというクラスが定義されています。これをsingle_class.pyという名前を付けて保存します。

class Person:
    def __init__(self, name):
        self.name = name

    def greet(self):
        print(f"I'm {self.name}.")

次に、single_class.pyと同じディレクトリで以下のコマンドを実行します。

> pyreverse -o png -p single single_class.py
Format png is not supported natively. Pyreverse will try to generate it using Graphviz...

ここで、-oオプションで出力形式、-pオプションで出力するファイル名の接尾辞を指定します。コマンドの実行後、以下のクラス図がclasses_single.pngというファイル名で出力されます。

クラス図
クラス図

上から順に、クラスの以下の情報が表示されています。

  • クラス名
  • 属性
  • メソッド

クラス間の関係
#

クラス間の関係として継承(汎化)、集約、コンポジションについて、それぞれクラス図として出力する例を示します。

継承(汎化)
#

継承とは、あるクラスの特性(属性やメソッドなど)を別のクラスに引き継ぐことです。以下のスクリプトをinheritance.pyとして保存します。先ほどのPersonクラスを継承したEmployeeクラスを定義しています。

class Person:
    def __init__(self, name):
        self.name = name

    def greet(self):
        print(f"I'm {self.name}.")

class Employee(Person):
    def __init__(self, name, company):
        super().__init__(name)
        self.company = company

    def greet2(self):
        print(f"I'm {self.name} from {self.company}.")

以下のコマンドを実行して、クラス図を出力します。

> pyreverse -o png -p inheritance inheritance.py

PersonクラスとEmployeeクラスが白い三角の矢印で結ばれており、継承(汎化)関係が出力されています。

継承のクラス図
継承のクラス図

集約
#

集約とは、以下のようなクラス間の関係です。

  • あるクラスが別のクラスの「部分」として表される
  • 全体のインスタンスが破棄されても、部分インスタンスが破棄されるとは限らない

以下のスクリプトaggregation.pyを作成します。Companyクラスのpresident属性はPersonインスタンスとなります。すなわち、PersonクラスはCompanyクラスの「部分」となります。また、型ヒントを使って、person引数はPersonインスタンスであることを示しています。

class Person:
    def __init__(self, name):
        self.name = name

    def greet(self):
        print(f"I'm {self.name}.")

class Company:
    def __init__(self, company_name, person:Person):
        self.company_name = company_name
        self.president = person

以下のコマンドを実行して、クラス図を出力します。

> pyreverse -o png -p aggregation aggregation.py

PersonクラスとCompanyクラスが白い菱形の矢印で結ばれており、集約関係が出力されています。矢印の緑の文字は、PersonクラスがCompanyクラスのpresident属性になることを示しています。

集約のクラス図
集約のクラス図

コンポジション
#

コンポジションとは、以下のようなクラス間の関係です。

  • あるクラスが別のクラスの「部分」として表される
  • 全体のインスタンスが破棄されると、部分インスタンスも破棄される

以下のスクリプトcomposition.pyを作成します。Personインスタンスの作成時に、Headインスタンス (Person.head) も作成されます。また、Personインスタンスが破棄されるときにPerson.headも破棄されるため、HeadクラスはPersonクラスのコンポジションとなります。

class Head:
    def __init__(self, wisdom:str):
        self.wisdom = wisdom

class Person:
    def __init__(self, name:str, wisdom:str):
        self.name = name
        self.head = Head(wisdom)

    def greet(self):
        print(f"I'm {self.name}.")

以下のコマンドを実行して、クラス図を出力します。

> pyreverse -o png -p composition composition.py

PersonクラスとHeadクラスが黒い菱形の矢印で結ばれており、コンポジション関係が出力されています。矢印の緑の文字は、HeadクラスがPersonクラスのhead属性になることを示しています。

コンポジションのクラス図
コンポジションのクラス図

参考
#

Helve
著者
Helve
関西在住、電機メーカ勤務のエンジニア。X(旧Twitter)で新着記事を配信中です

関連記事

pytestを実行するためのPythonパッケージのディレクトリ構成
·1661 文字·4 分
Pythonでパッケージを作成するとき、pytestによる自動テストに向いたディレクトリ構成をサンプルと合わせて解説します。
conda環境ではなくpip環境にspyderをインストールする【Windows環境】
··1669 文字·4 分
AnacondaやMinicondaなどのconda環境を使用せずに、pipのみの環境でPythonの統合開発環境Spyderを使用できるようにします。
pytestのテスト結果をHTMLファイルに出力する
·1256 文字·3 分
pytestとpytest-htmlを使って、Pythonコードのテスト結果をHTML形式で保存します。
pytestを使ったPythonのテスト
·1855 文字·4 分
pytestによる基本的なテストの実行方法と、複数のテストケースを記述する方法を解説します。
CasADiのOptiスタックでcallback関数を使って解の推移を取得する
·773 文字·2 分
最適化フレームワークCasADiのOptiスタックでcallback関数を使って、最適化ソルバの各反復における解の推移を取得する方法をまとめました。
CasADiで最適化の変数と制約をベクトル化する
·1082 文字·3 分
最適化フレームワークCasADiのOptiスタックで、多変数の最適化を簡潔に記述するため、変数と制約をベクトル化する方法をまとめました。