Reputation: 372
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?
Upvotes: 0
Views: 1225
Reputation: 4170
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}
Upvotes: 1