I'd like to get from
class Sum:
def __init__(self, a, b):
self._a = a
self._b = b
def evaluate(self):
return self._a + self._b
to
def add(a, b):
return a + b
class Sum:
def __init__(self, a, b):
self._a = a
self._b = b
def evaluate(self):
return add(self._a, self._b)
i.e., extract from method evaluate
the expression self._a + self._b
as a "free function" (a function that isn't a method). Is this possible with PyCharm's automatic refactorings?
I don't know whether this can be done with a single refactoring, but it can be done almost fully automated in 3-4 steps:
The steps in detail:
self._a + self._b
)Press Ctrl+Alt+M
or
from the context menu of the selection, choose Refactor > Extract > Method...
add
) and click OK.The result will look like this:
class Sum:
def __init__(self, a, b):
self._a = a
self._b = b
def evaluate(self):
return self.add()
def add(self):
return self._a + self._b
Now, let's pull the new method out of the class and turn it into a module-level function:
Press F6
or
from the context menu, choose Refactor > Move...
The result will look like this:
class Sum:
def __init__(self, a, b):
self._a = a
self._b = b
def evaluate(self):
return add(self._a, self._b)
def add(_a, _b):
return _a + _b
As you can see, the refactoring has correctly replaced the self
argument with two arguments for the operands. Unfortunately, it has used the _...
names of the corresponding "hidden" instance members.
_
) in the function's signature or where the function uses the argumentsPress Shift+F6
or
from the context menu of the selection, choose Refactor > Rename...
Repeat for the other function argument(s).
(In scenarios where you want to choose completely different names, simply place the cursor into the argument name to change without selecting a portion of it. Then the whole name will start out selected in the dialog input field and can be overwritten by typing something new.)
The result will look like this:
class Sum:
def __init__(self, a, b):
self._a = a
self._b = b
def evaluate(self):
return add(self._a, self._b)
def add(a, b):
return a + b
(or where-ever you want to place it)
As you can see, PyCharm placed the new top-level function after the class. I wanted to have it before it. Moving it with Shift+Alt+↑ as recommended in John's answer didn't work for me in PyCharm 2016.3.2 on GNOME, so I just selected the function, and cut it with Crtl+x and pasted it where I want it with Crtl+v.
There is not a direct way of doing what you want, but you can work around it:
self._a + self._b
statement and Right Click > Refactor > Extract > Method, or Ctrl + Alt + Madd
) > OK. This will generate a class function named as given. The process will also refactor the usage to match your case.self
, add a
, b
, etc.self.
everywhere inside the function. You can do this by find and replace: self.
in the first search bar > leave the second search bar empty and starting by the beginning of your file, click on the Replace button, until everything seems correct.evaluate
function erase the self.
that will be generated before the name of your generated function. Also pass the correct arguments to the function (ex. return add(self.a, self.b)
)And you are done, it is a bit of work and it is not that much automated, but it will save you some typing time!
This is tested in PyCharm 2017.1 pro edition
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With