15

I refactor my old code and want to change the names of functions in accordance with pep8. But I want to maintain backward compatibility with old parts of system (a complete refactoring of the project is impossible because function names is a part of the API and some users use the old client code).

Simple example, old code:

def helloFunc(name):
    print 'hello %s' % name

New:

def hello_func(name):
    print 'hello %s' % name

But both functions should work:

>>hello_func('Alex')
>>'hello Alex'
>>helloFunc('Alf')
>>'hello Alf'

I'm thinking about:

def helloFunc(name):
    hello_func(name)

, but I do not like it (in project about 50 functions, and it will look a messy, I think).

What is the best way to do it(excluding duplication ofcource)? Is it possible the creation of a some universal decorator?

Thanks.

vlad
  • 815
  • 2
  • 11
  • 25

4 Answers4

12

I think that for the time being, the easiest thing is to just create a new reference to the old function object:

def helloFunc():
    pass

hello_func = helloFunc

Of course, it would probably be more slightly more clean if you changed the name of the actual function to hello_func and then created the alias as:

helloFunc = hello_func

This is still a little messy because it clutters your module namespace unnecessarily. To get around that, you could also have a submodule that provides these "aliases". Then, for your users, it would be as simple as changing import module to import module.submodule as module, but you don't clutter your module namespace.

You could probably even use inspect to do something like this automagically (untested):

import inspect
import re
def underscore_to_camel(modinput,modadd):
    """
       Find all functions in modinput and add them to modadd.  
       In modadd, all the functions will be converted from name_with_underscore
       to camelCase
    """
    functions = inspect.getmembers(modinput,inspect.isfunction)
    for f in functions:
        camel_name = re.sub(r'_.',lambda x: x.group()[1].upper(),f.__name__)
        setattr(modadd,camel_name,f)
mgilson
  • 300,191
  • 65
  • 633
  • 696
  • 1
    @vlad -- I've added a function which I think will automatically add `function_with_underscores` from module `modinput` onto `modadd` as `functionWithUnderscores` (but it won't really work with `lambda` functions as they have no inspectable name (AFAIK) – mgilson Aug 16 '12 at 12:42
  • Thanks for `setattr`! That was obviously the way. – PlasmaBinturong Nov 16 '18 at 17:41
9

While the other answers are definitely true, it could be useful to rename the function to the new name and create an old one which emits a warning:

def func_new(a):
    do_stuff()

def funcOld(a):
    import warnings
    warnings.warn("funcOld should not be called any longer.")
    return func_new(a)
glglgl
  • 89,107
  • 13
  • 149
  • 217
  • 3
    better yet, use `warnings.warn('description', DeprecationWarning)` to explicitly note that this calling conversion is deprecated – Hubert Kario May 22 '18 at 12:24
4

You can bind your function object to another name in your module's namespace, e.g:

def funcOld(a):
    return a

func_new = funcOld
Rostyslav Dzinko
  • 39,424
  • 5
  • 49
  • 62
2

As your question sounds very much like deprecation or similar, I'd like to strongly recommend the use of decorators for cleaner code. In fact, someone in another thread has already created this for you.

Community
  • 1
  • 1
gustafbstrom
  • 1,622
  • 4
  • 25
  • 44