PyCharm 2018.3ヘルプ

PyCharmリファクタリングチュートリアル

このチュートリアルの内容

このチュートリアルでは、有理数を利用する単純なクラスの例を使用して、PyCharmで利用可能ないくつかのリファクタリングを示します。

前提条件

次の前提条件が満たされていることを確認してください。

  • PyCharmバージョン2016.2以降で作業しています。

  • プロジェクトはすでに作成されています。

例の準備

プロジェクトにPythonファイル rational.py を作成し、次のコードを追加します。

from collections import namedtuple class Rational(namedtuple('Rational', ['num', 'denom'])): def __new__(cls, num, denom): if denom == 0: raise ValueError('Denominator cannot be null') if denom < 0: num, denom = -num, -denom return super().__new__(cls, num, denom) def __str__(self): return '{}/{}'.format(self.num, self.denom)

有理数を単純化する

分子と分母を最大公約数で除算して有理数を単純化しましょう:

from collections import namedtuple class Rational(namedtuple('Rational', ['num', 'denom'])): def __new__(cls, num, denom): if denom == 0: raise ValueError('Denominator cannot be null') if denom < 0: num, denom = -num, -denom x = abs(num) y = abs(denom) while x: x, y = y % x, x factor = y return super().__new__(cls, num // factor, denom // factor) def __str__(self): return '{}/{}'.format(self.num, self.denom)

メソッドの抽出

ここでは、最も大きな共通の除数の検索を別の方法に抽出しましょう: これを行うには、ステートメントを選択します

x = abs(num) y = abs(denom) while x: x, y = y % x, x factor = y

Ctrl+Alt+Mを押します。ダイアログボックスが開き、メソッド名(gcd)を入力し、OKをクリックします。

@staticmethod def gcd(denom, num): x = abs(num) y = abs(denom) while x: x, y = y % x, x factor = y return factor

ローカル変数のインライン化とメソッドシグネチャの変更

インライン変数リファクタリングを使って変数 factorを取り除きましょう。これを行うには、問題の変数にキャレットを置き、 Ctrl+Alt+Nを押します。検出された factor 変数はすべてインライン展開されます。

次に、シグネチャーの変更を使用してパラメータ名を変更します。これを行うには、メソッド宣言行にキャレットを置き、 Ctrl+F6を押します。ダイアログボックス表示されたら、パラメータ denomnum の名前をそれぞれ xy に変更し、 icons nodes upLevel をクリックしてパラメータの順序を変更します。

次のコードで終わります:

@staticmethod def gcd(x, y): x = abs(x) y = abs(y) while x: x, y = y % x, x return y

クイック・フィックスの使用

さて、既存の静的メソッドを関数に変換しましょう: これを行うには、 Alt+Enterを押し、提案リストからstatic メソッドを関数に変換するを選択し、 Enterを押します:

from collections import namedtuple class Rational(namedtuple('Rational', ['num', 'denom'])): def __new__(cls, num, denom): if denom == 0: raise ValueError('Denominator cannot be null') if denom < 0: num, denom = -num, -denom factor = gcd(num, denom) return super().__new__(cls, num // factor, denom // factor) def __str__(self): return '{}/{}'.format(self.num, self.denom) def gcd(x, y): x = abs(x) y = abs(y) while x: x, y = y % x, x return y

関数を別のファイルに移動する

ここでは、関数を別のファイルに移動し、import文を追加します。これを行うには、関数 gcd 宣言にキャレットを置き、 F6を押します。開くダイアログボックスで、コピー先ファイル util.pyの完全修飾パスを指定します。このファイルは存在しませんが、自動的に作成されます:

def gcd(x, y): x = abs(x) y = abs(y) while x: x, y = y % x, x return y

インポート文も自動的に追加されます。したがって、ファイル rational.py は次のようになります。

from collections import namedtuple from util import gcd class Rational(namedtuple('Rational', ['num', 'denom'])): def __new__(cls, num, denom): if denom == 0: raise ValueError('Denominator cannot be null') if denom < 0: num, denom = -num, -denom factor = gcd(num, denom) return super().__new__(cls, num // factor, denom // factor) def __str__(self): return '{}/{}'.format(self.num, self.denom)

クラスRationalのさらなる変更

魔法の追加

次に、クラス Rationalのオブジェクトに対する加算/減算操作のための魔法の宣言を追加しましょう:

from collections import namedtuple from util import gcd class Rational(namedtuple('Rational', ['num', 'denom'])): def __new__(cls, num, denom): if denom == 0: raise ValueError('Denominator cannot be null') factor = gcd(num, denom) if denom < 0: num, denom = -num, -denom return super().__new__(cls, num // factor, denom // factor) def __str__(self): return '{}/{}'.format(self.num, self.denom) def __add__(self, other): if isinstance(other, int): other = Rational(other, 1) if isinstance(other, Rational): new_num = self.num * other.denom + other.num * self.denom new_denom = self.denom * other.denom return Rational(new_num, new_denom) return NotImplemented def __neg__(self): return Rational(-self.num, self.denom) def __radd__(self, other): return self + other def __sub__(self, other): return self + (-other) def __rsub__(self, other): return -self + other

メソッドの抽出とクイックフィックスの使用

次に、式 Rational(other, 1) を別のメソッドに抽出します。これを行うには、前述の式にキャレットを置き、 Ctrl+Alt+M を押し、開いているダイアログボックスに新しいメソッド名 from_intを入力します。

最後に、メソッド from_int 宣言にキャレットを置き、 Alt+Enterを押し、提案リストからメソッドを static にするを選択し、 Enterを押します。

@staticmethod def from_int(other): return Rational(other, 1)

最後に、パラメータ other の名前を numberに変更しましょう。これを行うには、パラメータにキャレットを置き、 Shift+F6を押します。

スーパークラスの抽出

次に、メソッド __radd____sub__ 、および __rsub__ の実装をスーパークラスに移します。また、メソッド __neg____add__ を抽象化します。

これは完了です...クラス Rational 宣言にカレットを置き、コンテキストメニューでリファクタリング | 抽出を指し、スーパークラスの抽出...を選択します。次に、表示されるダイアログボックスで、スーパークラスの名前(ここでは AdditiveMixin)を指定し、スーパークラスに追加するメソッドを選択します。メソッド __neg__ および __add__に対しては、列抽象にするチェックボックスを選択します。

次のコードで終了します。

from abc import abstractmethod, ABCMeta from collections import namedtuple from util import gcd class AdditiveMixin(metaclass=ABCMeta): @abstractmethod def __add__(self, other): pass @abstractmethod def __neg__(self): pass def __radd__(self, other): return self + other def __sub__(self, other): return self + (-other) def __rsub__(self, other): return -self + other class Rational(namedtuple('Rational', ['num', 'denom']), AdditiveMixin): def __new__(cls, num, denom): if denom == 0: raise ValueError('Denominator cannot be null') factor = gcd(num, denom) if denom < 0: num, denom = -num, -denom return super().__new__(cls, num // factor, denom // factor) def __str__(self): return '{}/{}'.format(self.num, self.denom) def __add__(self, other): if isinstance(other, int): other = self.from_int(other) if isinstance(other, Rational): new_num = self.num * other.denom + other.num * self.denom new_denom = self.denom * other.denom return Rational(new_num, new_denom) return NotImplemented def from_int(self, number): return Rational(number, 1) def __neg__(self): return Rational(-self.num, self.denom)
最終更新日: 2018年12月13日

関連事項