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 ,从建议列表中选择 将 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
将函数移动到另一个文件
现在,我们将函数移动到一个单独的文件并添加导入语句。 为此,将光标放在函数 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 ,从建议列表中选择 将方法设为静态 ,然后按 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年 9月 26日