Alternative way to use getattr in python? - python

I am trying to call a object functions which also allows several different function to be called through same object :
for eg: sort(), facet(),exclude() are different functions with their
arguments and sort_flag, facet_flag and exclude_flag as condition set to true or false
can be called as:
si = sunburnt.SolrInterface("url","schema.xml")
response = si.query(arg1).facet(arg2).sort(arg3).exclude(arg4)
There can be certaing cases when I dont need to call all of these functions at same time or may be I dont have all the arguments to call these functions or vice versa. In that situtation how can I call si.facet(args).sort(args) something like this:
if sort_flag:
--append sort function to the query
if exclude_flag:
-- append exclude function
There can be alternative to do that using getattr but its confusing to use it using arguments of function and at same time it may generate lot of if check statements (for 3 flags close to 3 factorial statements)

I'm not sure I understood you, but can't you do this?
si = sunburnt.SolrInterface("url","schema.xml")
query = si.query(arg1).facet(arg2)
if sort_flag:
query = query.sort(arg3)
if exclude_flag:
query = query.exclude(arg4)
response = query.execute()

Related

Calling a python function

I am trying to make a python library that allows me to make custom tkinter widgets that are more aesthetically pleasing than the built-in ones. However, I have run into a problem while defining a few functions.
The problem stems from the difference between functions like append() and str(). While the append function works as follows...
somelist = ['a', 'b', 'c']
somelist.append('d')
The str() function works like this...
somenumber = 99
somenumber_text = str(some_number)
You 'call upon' the append function by (1) stating the list that you are modifying (somelist), (2) adding a period, and (3) actually naming the append funtion itself (append()). Meanwhile you 'call upon' the str function by placing a positional argument (somenumber) within its argument area. I have no idea why there is this difference, and more importantly if there is a way to specify which method to use to 'call upon' a function that I define myself?
Thanks...
In Python, function is a group of related statements that perform a specific task.
Functions help break our program into smaller and modular chunks. As our program grows larger and larger, functions make it more organized and manageable.
Furthermore, it avoids repetition and makes code reusable.
Syntax of Function
def function_name(parameters):
"""docstring"""
statement(s)
Above shown is a function definition which consists of following components.
Keyword def marks the start of function header.
A function name to uniquely identify it. Function naming follows the same rules of writing identifiers in Python.
Parameters (arguments) through which we pass values to a function. They are optional.
A colon (:) to mark the end of function header.
Optional documentation string (docstring) to describe what the function does.
One or more valid python statements that make up the function body. Statements must have same indentation level (usually 4 spaces).
An optional return statement to return a value from the function.
You really don't need to create a class, or any methods. You can make a plain-old function that's similar to bind, and just take the widget to bind as a normal parameter. For example:
def bind_multi(widget, callback, *events):
for event in events:
widget.bind(event, callback)
That means you have to call this function as bind_multi(mybutton, callback, event1, event2) instead of mybutton.bind_multi(callback, event1, event2), but there's nothing wrong with that.

Python call a function by indirection

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)

How to pass parameters in a Python Dispatch Table

I am trying to construct a dispatch the following way:
def run_nn(type=None):
print type, 'nn'
return
def run_svm(type=None):
print type, 'svm'
return
action = {'nn' : run_nn( type=None),
'svm' : run_svm(type=None),}
I want the function to be executed only when called with something like:
action.get('nn',type='foo')
With expectation it to print:
foo nn
But it breaks giving:
TypeError: get() takes no keyword arguments
What's the right way to do it?
Furthermore, two functions run_nn() and run_svm() were executed without even being called. I don't want that. How can I avoid it?
You're calling the functions while building the dictionary. You should instead put the function objects in the dict without calling them. And afterwards, get the appropriate function from the dict and call it with the keyword argument.
What you want is:
action = {'nn' : run_nn,
'svm' : run_svm,}
...
action.get('nn')(type='foo') # get function object from dict and then call it.
I'll suggest you use action['nn'] over action.get('nn') since you're not specifying any default callable in the get method; the get method returns None when you don't specify one. A KeyError is much more intuitive than a TypeError NoneType object is not callable in this scenario.
On another note, you can drop those return statements as you aren't actually returning anything. Your function will still return without them.
BTW, I have the feeling your function(s) want to change behavior depending on type (although your type is counter-intuitive as it is always a string). In any case, you may have a look at functools.singledispatch. That'll transform your function(s) into a single-dispatch generic function with the possibility to create several overloaded implementations.
Finally, although type does make for a good argument name, you will run into problems when you need to use the builtin type in your function.

Does python alter the parameters if not passed while executing a function?

for example:
#creating the function with params
def symlinks(release_path, deploy_to, settings_file, roll_back=False, is_file=False):
#doing something with all the params
#executing the function
symlinks(releasepath, deploypath, settingsfile, is_file=true)
So there are multiple ways of passing parameters to functions in python, is the above one valid?
i tried symlinks(releasepath,deploypath,True) but seems like it is impacting roll_back.
Would the roll_back param be still false?
Arguably the coolest way for you to find the answer to your question, would be using inspect.getcallargs. You can learn a lot by playing with it.
import inspect
inspect.getcallargs(symlinks, 'releasepath', 'deploypath', 'settingsfile', is_file=True)
=>
{'deploy_to': 'deploypath',
'is_file': True,
'release_path': 'releasepath',
'roll_back': False,
'settings_file': 'settingsfile'}
Python will bind the passed in values to the positional parameter names in the order they are passed, unless you specify a parameter name explicitly.
In your case, if you invoked the function with: symlinks(releasepath,deploypath,True), then the default values would be used for the remaining 2 parameters (roll_back and is_file).
See documentation: https://docs.python.org/2/tutorial/controlflow.html#keyword-arguments

Passing arguments to functions in Python using inspect

I have a Python script which creates a dictionary of its own functions and I'd like it to execute them by reading in a function name and arguments using YARP (knowledge of YARP is irrelevant to this question though).
I create a list of strings called "inc" which is populated by values coming into the program. The first item is a function name, and any other strings in the list are arguments. I create a dictionary called "methods" where the key is the function name and the value is a reference to the function object (using the inspect module). I store the return value of the function in a variable "result".
The snippet below shows a simplified version of what I'm using so far, which works fine, but can't handle functions with more than one argument. To circumvent this I use a list if a function needs more parameters:
if len(inc) == 1:
result = methods[inc[0]]() # call method with 0 arguments
elif len(inc) == 2:
result = methods[inc[0]](inc[1]) # call method passing a string
else:
args = []
result = methods(inc[0])(inc[1:]) # call method passing a list
Ideally, I'd like to change this so that my functions can have any number of arguments, but I can't figure out how I can do this. I'm new to Python and I have looked at the documentation and various websites - I just can't find a solution. I've tried things like creating a tuple of the arguments, but that doesn't work either as it ends up passing the whole tuple in as one parameter.
Is there a better solution to this problem, like creating some kind of object which represents a set of parameters and passing that into the function? Any suggestions would be greatly appreciated!
You should check out https://stackoverflow.com/a/3394898/1395668.
The magic you are looking for is the *. Apply this to your list and it unpacks the items into the argument fields of your function:
a = [ 1, 2, 3]
def myfunc(a, b, c):
return a + b + c
print myfunc(*a)
Check out ** for the same approach for dict
It's a bit strange to have this kind of mixed structure:
inc = [func_name, arg1, arg2, ...]
Wouldn't it be much more natural to have two separate bits of information?
func_name = ...
args = [arg1, arg2, ...]
The you could do
methods[func_name](*args)
(Usually, I wouldn't bind the functions name to a variable, but preferably the function itself.)

Categories