Moving function/method to class
Asked Answered
I

1

13

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.

Ician answered 17/5, 2017 at 17:14 Comment(2)
Why do you want a class at all? It doesn't seem to be useful here.Verticillaster
Do you want to pass the args on the call of the class or the method?Ger
E
9

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.

Eldridge answered 17/5, 2017 at 19:15 Comment(2)
grundic, how did you come up with this regex? Did you write it specifically to answer this question? Did you write it for your own purposes? Did you find it somewhere? Are there other regexes like this one that could be useful for refactoring? Where would one find them?Canon
I think I just wrote this regex for this question.Eldridge

© 2022 - 2024 — McMap. All rights reserved.