I'm pretty new to Python and I have a situation where I have a variable representing a function inside of a module and I'm wondering how to call it dynamically. I have filters.py:
def scale(image, width, height):
pass
And then in another script I have something like:
import filters
def process_images(method='scale', options):
filters[method](**options)
... but that doesn't work obviously. If someone could fill me in on the proper way to do this, or let me know if there is a better way to pass around functions as parameters that would be awesome.
you need built-in getattr:
getattr(filters, method)(**options)
To avoid the problem, you could pass the function directly, instead of "by name":
def process_images(method=filters.scale, options):
method(**options)
If you have a special reason to use a string instead, you can use getattr as suggested by SilentGhost.
import filters
def process_images(function=filters.scale, options):
function(**options)
This can then be called like, for example:
process_images(filters.rotate, **rotate_options)
Note that having a default function arg doesn't seem like a good idea -- it's not intuitively obvious why filters.scale is the default out of several possible image-processing operations.
Related
I am creating a module in which I'm defining multiple functions and I want to give the users some help regarding it, just like the help() function does. Still, I'm not quite sure how I do that, so can someone help me with it, for example, if I want help regarding this function, what will I have to do?
def shanky_calculate_average(*args):
my_average = sum(args) / len(args)
return my_average
I just want to know if I can get help in the same way as you can on things like help(pandas.read_excel)
What help() actually does is printing the function name with arguments and its docstring. Docstrings are comments directly after the function or class definition and are declared using either '''triple single quotes''' or """triple double quotes""".
So doing something like this:
def shanky_calculate_average(*args):
'''
Computes the average of the arguments.
Example: shanky_calculate_average(1,2,3,4)
'''
my_average = sum(args) / len(args)
return my_average
will result in help(shanky_calculate_average)
to print
shanky_calculate_average(*args)
Computes the average of the arguments.
Example: shanky_calculate_average(1,2,3,4)
As a sidenote, you can also access docstrings via the __doc__ property of the object like this: shanky_calculate_average.__doc__.
I have a class and multiple functions that run in succession as:
class ClassA():
def __init__(self):
....
def calc_A(self, param1, param2 ,param3):
res = self.__calc_B(param1=param1)
res_2 = self.__calc_C(res=res, param2, param3)
def __calc_B(self, param1):
return param1**2
def __calc_C(self, param1):
return res + param1
As you can see calc_A() takes in parameters for __calc_B() and __calc_C(). The original class is getting pretty complex as I need quite a number of parameters to run all the functions and I see myself repeating a lot of docstrings for params that get used in more than one function.
Question 1:
Is it best practice to just use *args for __calc_B() and __calc_C() or should it be handled in a completely different way?
Question 2:
Additionally, do I describe the parameters in the docstring in calc_A() or in every function?
*args is never best practice because looking at the function you won't know what is supposed to go into the function. Only by writing documentation to the function can a user figure out what the inputs are supposed to be. Making input parameters explicit if possible is generally favored, because they show up when the user calls help.
Docstrings mainly serve to help users who can learn what the function does by calling help(function). __calc_B and __calc_C seem to be functions that are not supposed to be used by the user, so a docstring is not strictly necessary. It is most important to choose good descriptive names for these functions so that you or someone else who needs to understand the code can figure out what it does. You could still write a docstring or comments if it's a particularly difficult function, but they don't need to be so detailed.
If you find no other alternatives, there are ways of generating docstrings dynamically but this is generally not recommended.
Windows7, Python2.7 MPD2.
I am writing a program to control MPD.
MPD has several (over 50) different functions.
Normally one would make a call in the form:
mpd_client.pause()
#or
mpd_client.playlistmove(playlist_name, old_pos, new_pos)
I want to encapsulate all the separate calls in one function so I can use a single try / except.
I am thinking I want to use some sort of lambda, and *args but I have little experience with either of those.
In the body of my program, I want to call something like this:
MPD('pause')
#or
MPD('playlistmove', playlist_name, old_pos, new_pos)
I envision my function looking something like...
def MPD(required_param, *args):
try:
mpd_client.required_param(args)
except:
...
of course, this isn't working.
Short of writing a huge switch statement and 50 different try structures, is there a way I can use lambda?
maybe something like:
lambda m=mpd_client.required_param: m(args)
but, this isn't working either.
I don't know.
Thanks, Mark.
You need to use getattr() to retrieve the actual method to call by name:
getattr(mpd_client, required_param)(*args)
(Note that you also need the * in front of the args for the function call as well, to re-expand the argument list back into separate arguments.)
what you need is object.__dict__, as in your code:
func = mpd_client.__dict__['pause']
func()
func = mpd_client.__dict__['playlistmove']
func(playlist_name, old_pos, new_pos)
Can you please help me guys. I believe I've got pretty easy questions but don't want to stuff up with my assignment. I'm going to have Class in my module, this class will have few functions.
I just want to be sure it works alright and this is a not ugly code practice.
I.e. my first function test_info accepts one parameter test_code and returns something and the second function check_class accepts two parameter, one of them is called test_code as well
Can I use same argument name: test_code? Is it normal code practice?
def test_info (self, test_code):
my_test_code = test_code
#here we'll be using my_test_code to get info from txt file and return other info
def check_class (self, test_code, other_arg):
my_test_code = test_code
#here some code goes
Also is it fine to use my_test_code in both functions to get argument value or is it better to use different ones like my_test_code_g etc.
Many thanks
Yes you may.
The two variables test_code are defined only in the scope of their respective functions and therefore will not interfere with one another since the other functions lie outside their scope.
Same goes for my_test_code
Read online about variable scopes. Here is a good start
There is no technical reason to resolve this one way or another. But if the variables don't serve exactly the same purpose in both functions, it's confusing for a human reader if they have the same name.
I'm creating a custom module to help me write python faster with less code and cleaner syntax.
At the moment i am creating a function which is a cleaner version of wx.Accelerator.
By the end of this, i expect:
accel_tbl = wx.AcceleratorTable([(wx.ACCEL_CTRL, ord('O'), PUT_ID_HERE),
(wx.ACCEL_CTRL, ord('S'), PUT_ID_HERE)])
self.SetAcceleratorTable(accel_tbl)
to become:
accelerate((wx.ACCEL_CTRL,'O',PUT_ID_HERE),
(wx.ACCEL_CTRL,'S',PUT_ID_HERE))
The only problem is.. I dont know where to start.... I know how to process information through parameters, but i've never learnt how to process multiple tuples with dynamic information inside parameters.
Can someone provide insight? Thankyou.
EDIT:
Current code:
## Create a cleaner accelerator
def accelerate(*args):
accel_tbl = wx.AcceleratorTable(list(args))
wx.SetAcceleratorTable(accel_tbl)
Current call:
import Sky
Sky.accelerate((wx.ACCEL_CTRL,'s',wx.ID_ANY),
(wx.ACCEL_CTRL,'t',wx.ID_ANY))
Add this method to your custom wx.Window class:
def accelerate(self,*args):
accel_tbl = wx.AcceleratorTable(args)
self.SetAcceleratorTable(accel_tbl)
Then invoke it as follows:
win = YourCustomWindowClass(PUT_WINDOW_ARGUMENTS_HERE)
win.accelerate((wx.ACCEL_CTRL,'O',PUT_ID_HERE),(wx.ACCEL_CTRL,'S',PUT_ID_HERE))
Alternatively, you can define it as a function taking a wx.Window argument as follows:
def accelerate(win,*args):
accel_tbl = wx.AcceleratorTable(args)
win.SetAcceleratorTable(accel_tbl)
The *args represents all the positional arguments as a tuple. If AcceleratorTable really requires a list, you can use list(args) instead as the argument (i.e. accel_tbl = wx.AcceleratorTable(list(args))).
You can learn about *args here.