Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Moving function/method to class

Using pycharm, I wish to refactor methods into a class. (Staticmethod would do) Current:

import math

class Solver(object):
   def __init__(self, a, b, c):
       self.a = a
       self.b = b
       self.c = c


def demo(b, a, c):
   d = b ** 2 - 4 * a * c
   if d >= 0:
       disc = math.sqrt(d)
       root1 = (- b + disc) / (2 * a)
       root2 = (- b - disc) / (2 * a)
       print(root1, root2)
       return root1, root2
   else:
       raise Exception


s = Solver(2, 123, 0.025)
demo(s.b, s.a, s.c)

Desired:

import math

class Solver(object):
     def __init__(self,a,b,c):
            self.a = a
            self.b = b
            self.c = c

    def demo(self, a, b, c):
            d = self.b ** 2 - 4 * self.a * self.c
            if d >= 0:
                disc = math.sqrt(d)
                root1 = (- self.b + disc) / (2 * self.a)
                root2 = (- self.b - disc) / (2 * self.a)
                print(root1, root2)
                return root1, root2
            else:
                raise Exception

Solver(2, 123, 0.025).demo()

I am basically trying to get the opposite functionality to: "Moving function/method to the top-level"

as described here: https://www.jetbrains.com/help/pycharm/2017.1/move-refactorings.html

I wouldn't mind on settling for a class with no init params.

like image 310
oria general Avatar asked May 17 '17 17:05

oria general


1 Answers

By default there is no such option: PyCharm is quite good at refactoring classes and methods, but can't do much with standalone functions. Though, there is a solution for your problem: regex!

Basically, what you have to do is:

  1. Change function to bounded method (you already did that in your example)
  2. Replace all occurrences of old method call with refactored one.

Here is the regex which would let you do that for aforementioned example:

([\w]+)[ \t]+=[ \t](Solver[ \t]*\(([\d.]+)[ \t]*,[ \t]*([\d.]+)[ \t]*,[ \t]*([\d.]+)[ \t]*\))\n\r?demo[ \t]*\(\1\.b[ \t]*,[ \t]*\1\.a[ \t]*,[ \t]*\1\.c[ \t]*\)

And here is the replacement:

$2\.demo()

Now you can select Edit -> Find -> Replace in Path in PyCharm, check regex option, paste first regex to first field and second to next one. I've tested that locally with one file and it worked well. And here is regex101 example so you can play with it and test it.

This would be useful if you have a lot of usages of that method, otherwise it could be faster to do that manually.

like image 65
grundic Avatar answered Sep 20 '22 05:09

grundic