PyCharm 重构教程
本教程介绍的内容
本教程通过一个使用有理数的简单类为例,展示 PyCharm 中可用的一些重构。
准备示例
在您的项目中创建一个 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 ,然后点击 确定:
@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。 在打开的 对话框 中,将参数 denom 和 num 分别重命名为 x 和 y ,并点击
以更改参数顺序。
您将得到以下代码:
@staticmethod
def gcd(x, y):
x = abs(x)
y = abs(y)
while x:
x, y = y % x, x
return y
使用快速修复
现在,将现有的静态方法转换为函数。 为此,按下 Alt+Enter ,在建议列表中选择 将静态方法转换为函数 ,然后按下 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
还会自动添加 import 语句。 因此,文件 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 ,在建议列表中选择 将方法设为静态 ,然后按下 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)
最后修改日期: 2025年 12月 2日