Feature Spotlight: Refactoring Python code
We all know that code can’t be crafted ideally from the beginning, especially in large projects. There is always a need to change something during the active development or maintenance stages. In fact refactoring is something you do all the time in small steps. You don’t simply decide to refactor – you change your code because you want to do something else, and refactoring helps you do that other thing.
As Martin Fowler says: “Refactoring is a controlled technique for improving the design of an existing code base. Its essence is applying a series of small behavior-preserving transformations, each of which is “too small to be worth doing”. However the cumulative effect of each of these transformations is quite significant.”
Refactorings can be a simple rename of a variable or extracting a superclass from the body of an existing class. PyCharm provides many refactorings for the various languages it supports. It carries them out automatically, making sure existing code is updated and will not break.
Today we’ll take a look at the refactoring features available in PyCharm that reduce the risk of introducing errors while you are carrying out the restructuring.
Refactoring in PyCharm
Before we dive into all available refactorings, let’s see what a typical refactoring looks like. Sure, they all do different things, still there are some things they have in common. Let’s try renaming a class in our code.
To do this, we can use the Refactor | Rename… context menu on a class name, or place the cursor on it and use the Shift+F6 keyboard shortcut to invoke the rename refactoring immediately:
For every refactoring, we’ll get a different dialog in which we can provide the options for it. In this case we have to provide a new name for the class we’re about to rename. Some of the options in this dialog will be available for other refactorings as well: we can (optionally) search in comments and strings, search for text occurrences, and so on.
When invoking a refactoring in PyCharm, the IDE will:
- Perform the refactoring
- Track down and correct the affected code references automatically
- Warn about occurrences it cannot update automatically
- Save the previous state of your code, so you can always revert safely
If you are unsure about the outcome, consider clicking the Preview button before running the refactoring. It will open the Find Refactoring Preview tool window and show you all of the actions the refactoring will perform:
In this case, it will:
- Rename the class and its derived class
- Update all code references
- Update one of the import statements in the project
We can filter and search in this tool window. Also we can optionally select one of the occurrences and use Delete to have PyCharm ignore it whenever we perform the refactoring:
This may come in handy when we’re also searching and replacing in comments and strings. Usually we will not exclude actual code refactorings.
Clicking Do Refactor will perform the refactoring and update our project’s codebase.
Another important thing to know is that PyCharm lets you undo everything, and that includes refactorings, no matter how complex code transformations they cause. Just press Ctrl + Z (Cmd + Z for Mac), and you’re back to where you were before inadvertently scrambling a few thousands lines of code. Another way to get back in code state is to use Local history by invoking Ctrl + Shift + A (Cmd + Shift +A for Mac) and typing “Local history”:
More information on local history can be found in one of our previous blog posts.
The Refactor This Action
While most refactorings in PyCharm have their own shortcuts, we may not know all of them. We may also be unfamiliar with the various refactorings available for a given file or a symbol. And that’s where the Refactor This action comes in handy!
In the Project View, Structure Tool Window, Editor or a UML Class Diagram, place the cursor on any file or symbol and use the Refactor | Refactor This context menu or press Ctrl+Shift+Alt+T (Ctrl-T on Mac OS X). This will display a pop-up with the different refactorings that we could carry out:
Using the up/down keys and Enter (or the numeric identifier for each entry in the pop-up) we can invoke the refactoring.
PyCharm comes with lots of refactorings. I won’t go over all of them them here, but rather list the most essential ones. For every refactoring, I’ll add a link to the PyCharm Web Help which contains a full description of all available options for a given refactoring.
Note: All refactorings are available from the Refactor context menu or via their respective keyboard shortcuts.
- Refactor this: Ctrl+Shift+Alt+T (Ctrl-T on Mac OS X)
- Rename: Shift + F6
- Copy a class or file: F5
- Move a class or file: F6
- Extract a constant: Alt + Ctrl + C (Alt + Cmd + C for Mac)
- Extract a variable: Alt + Ctrl + V (Alt + Cmd + V for Mac)
- Extract a method: Alt + Ctrl + M (Alt + Cmd + M for Mac)
- Extract a field: Alt + Ctrl + F (Alt+ Cmd + F for Mac)
- Extract a parameter: Alt + Ctrl+ P (Alt+ Cmd + P for Mac)
- Extract a super class
- Change signature: Ctrl + F6 (Cmd + F6 for Mac)
- Safe Delete: Alt + Delete
- Inline a class or method: Alt + Ctrl + N (Alt + Cmd + N for Mac)
- Pull members up/down
- Invert Boolean
That’s all for today. I hope you’ll enjoy this wide range of refactoring capabilities provided by PyCharm.
See you next week, and refactor safely!