0

Say I have some very long function module.my_function that's something like this:

def my_function(param1,param2,param3='foo',param4='bar',param5=None,...)

With a large number of args and keyword args. I want this function to be usable both as a part of module module and as a class method for myClass. The code for the function will remain exactly the same, but in myClass a few keyword args may take different default values.

What's the best way of doing this? Previously I was doing something like:

class myCLass(object):
    def __init__(self,...
    def my_function(self, param1,param2,param3='hello',param4='qaz',param5=['baz'],...):
        module.my_function(param1,param2,param3=param3,param4=param4,param5=param5,...)

It seems a little silly to write all these arguments that many times, especially with a very large number of arguments. I also considered doing something like module.my_function(**locals()) inside the class method, but I'm not sure how to handle the self argument and I don't know if this would lead to other issues.

I could just copy paste the entire code for the function, but that doesn't really seem very efficient, when all that's changing is a few default values and the code for my_function is very long. Any ideas?

2
  • Is there a reason that all of the keyword args have to be explicit and you can't just use kwargs? Commented Jul 24, 2016 at 5:17
  • The reason is probably that I'm not too experienced a coder... how would I use kwargs in this situation and set some of the default values to something different? Say 3-5 in the above example are the ones I'm changing.. would I just specify params 1-5 and use kwargs for the rest? Commented Jul 24, 2016 at 5:32

1 Answer 1

1

You can convert the function to bound method by calling its __get__ method (since all function as descriptors as well, thus have this method)

def t(*args, **kwargs):
    print(args)
    print(kwargs)

class Test():
    pass
Test.t = t.__get__(Test(), Test) # binding to the instance of Test

For example

Test().t(1,2, x=1, y=2)
(<__main__.Test object at 0x7fd7f6d845f8>, 1, 2)
{'y': 2, 'x': 1}

Note that the instance is also passed as an positional argument. That is if you want you function to be instance method, the function should have been written in such a way that first argument behaves as instance of the class. Else, you can bind the function to None instance and the class, which will be like staticmethod.

Test.tt = t.__get__(None, Test)
Test.tt(1,2,x=1, y=2)
(1, 2)
{'y': 2, 'x': 1}

Furthermore, to make it a classmethod (first argument is class):

Test.ttt = t.__get__(Test, None) # bind to class
Test.ttt(1,2, x=1, y=2)
(<class '__main__.Test'>, 1, 2)
{'y': 2, 'x': 1}
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.