Dynamic method in python - python

I'm trying to create a method in python, which accepts 1-n number of parameters, calls the same method on each and returns the result. For example;
(Note this is pseudo code, I'm just typing these methods/syntax on the fly - new to python )
def get_pid(*params):
pidlist = []
for param in params:
pidlist.add(os.getpid(param))
return pidlist
Ideally I would like to do something like
x, y = get_pid("process1", "process2")
Where I can add as many parameters as I want - and the method to be as 'pythonic' and compact as possible. I think there may be a better way than looping over the parameters and appending to a list?
Any suggestions/tips?

Your code already works. Your function accepts 0 or more arguments, and returns the results for each function call. There is but a minor mistake in it; you should use list.append(); there is no list.add() method.
You could use a list comprehension here to do the same work in one line:
def get_pid(*params):
return [os.getpid(param) for param in params]
You could just inline this; make it a generator expression perhaps:
x, y = (os.getpid(param) for param in ("process1", "process2"))
You could also use the map() function for this:
x, y = map(os.getpid, ("process1", "process2"))

You can use yield to create a generator:
def get_pid(*params):
for param in params:
yield os.getpid(param)
x, y = get_pid("process1", "process2")
print(x, y)

Related

Pythonic way to override variables in function with arguments

New to python and have situation like this:
myfun.py:
def fun(x, ...):
par1 = ...
par2 = ...
... # many pars
parn = ...
return #*long and complicated function of all the pars and x inputs*
Sometimes I'd like to modify one or more of the pars without modifying myfun.py itself. I know I could:
Define every par as an argument to fun and give it a default value
Make a dictionary par_dict = {'par1': ..., ...} then wherever I have par1 in my return code replace it with par_dict['par1']. Then use par_dict.update() to take a dictionary argument and update my pars.
Any clean and compact alternatives to these options? I'd like something like this:
fun(x_in, par10=5)
# output uses 5 where par10 occurs in the function, in other words the argument to the function overrides the values set inside the function.
Thank you.
The most pythonic way I find is something like this:
First you define the function, such as
def fun(x, *, par1=1, par2=2, ..., parn=999):
return # function using all params
The function has its default settings, with the predefined values for the parameters. The * as second argument is to prevent the use of positional arguments for further than the x variable.
Then you may use configurable dictionaries to alter the params:
params = {
'par1': 10,
'par2': 20,
...
'parn': 0}
fun(X, **params)
The **params distributes the variables declared in the dictionary to the input parameters in the function.
EDIT It is also possible to use nested functions, like this:
def outer(par1=1, par2=2, ..., parn=999):
def inner(x):
return # function using x and pars...
return inner
Notice that the params of the outer function don't need to have default values. Then you "instance" the function, using it with any set of new params.
params = {...} # like the previous example
fun = outer(**params)
fun(X)
You can use outer to create different functions, that behaves as the params you input, for instance:
params1 = {...}
fun1 = outer(**params1)
params2 = {...}
fun2 = outer(**params2)
a = fun1(X)
b = fun2(X)
In this case a and b are different.

The more pythonic way to call more than one function [duplicate]

In Python we can assign a function to a variable. For example, the math.sine function:
sin = math.sin
rad = math.radians
print sin(rad(my_number_in_degrees))
Is there any easy way of assigning multiple functions (ie, a function of a function) to a variable? For example:
sin = math.sin(math.radians) # I cannot use this with brackets
print sin (my_number_in_degrees)
Just create a wrapper function:
def sin_rad(degrees):
return math.sin(math.radians(degrees))
Call your wrapper function as normal:
print sin_rad(my_number_in_degrees)
I think what the author wants is some form of functional chaining. In general, this is difficult, but may be possible for functions that
take a single argument,
return a single value,
the return values for the previous function in the list is of the same type as that of the input type of the next function is the list
Let us say that there is a list of functions that we need to chain, off of which take a single argument, and return a single argument. Also, the types are consistent. Something like this ...
functions = [np.sin, np.cos, np.abs]
Would it be possible to write a general function that chains all of these together? Well, we can use reduce although, Guido doesn't particularly like the map, reduce implementations and was about to take them out ...
Something like this ...
>>> reduce(lambda m, n: n(m), functions, 3)
0.99005908575986534
Now how do we create a function that does this? Well, just create a function that takes a value and returns a function:
import numpy as np
def chainFunctions(functions):
def innerFunction(y):
return reduce(lambda m, n: n(m), functions, y)
return innerFunction
if __name__ == '__main__':
functions = [np.sin, np.cos, np.abs]
ch = chainFunctions( functions )
print ch(3)
You could write a helper function to perform the function composition for you and use it to create the kind of variable you want. Some nice features are that it can combine a variable number of functions together that each accept a variable number of arguments.
import math
try:
reduce
except NameError: # Python 3
from functools import reduce
def compose(*funcs):
""" Compose a group of functions (f(g(h(...)))) into a single composite func. """
return reduce(lambda f, g: lambda *args, **kwargs: f(g(*args, **kwargs)), funcs)
sindeg = compose(math.sin, math.radians)
print(sindeg(90)) # -> 1.0

Using string as literal expression in function argument in Python

Let's say I have a function that can take various kinds of parameter values, but I don't want to (as a constraint) pass arguments explicitly. Instead, I want to pass them as a string.:
def func(param)
return param+param
a = 'param=4'
func(<do something to a>(a))
>>8
Is this possible in python?
I want to use this idea in Django to create Query filters based on GET parameters in a dictionary and then just chain them using their keys.
lookup_dic = {'user': 'author=user',
'draft': 'Q(publish_date_lte=timezone.now())|
Q(publish_date_isnull=True)'}
Based on whether the user and draft keywords are passed in the GET parameters, this would be read out like:
queryset.objects.filter(author=user).filter(Q(publish_date_lte=timezone.now())|
Q(publish_date_isnull=True))
I understand that I can do this by replacing the author=user by Q(author__name=user), but I wanted to know if this string comprehension feature is implemented in python in general?
Use eval
def func(param=0):
return param+param
a = 'param=4'
eval('func(' + a +')')
Are you looking for this?
def func(param):
return param + param
a = 'param=4'
parameter, value = a.split("=")
print(func(**{parameter: int(value)}))
# >> 8

How to save value returned from python function if call does not capture return

Let's say I have a python function, where x and y are relatively large objects (lists, NumPy matrices, etc.):
def myfun(x):
y=some complicated function of x
return y
If in an interactive session the user calls this as:
myfun(5)
The call is basically useless, since y is lost. Let's also suppose the function takes a while to run. Is there a way to retrieve the answer, so the user doesn't have to re-run, i.e. answer=myfun(5)? Alternatively, what is a good (pythonic) way to write the function to make it 'fool-proof' for this scenario? Some not-so-great options are:
Require a parameter that stores the value, e.g.
def myfun(x,y):
y = some complicated function of x
return y
Or maybe:
def myfun(x):
y = some complicated function of x
global temp
temp = y
return y
In the latter case, if a user then mistakenly called myfun(5), there's the option of y=temp to get the answer back.. but using global just seems wrong.
y=_
assuming you are in the interactive python console. _ is magic that holds the last "result"

Passing an array/list into a Python function

I've been looking at passing arrays, or lists, as Python tends to call them, into a function.
I read something about using *args, such as:
def someFunc(*args)
for x in args
print x
But not sure if this is right/wrong. Nothing seems to work as I want. I'm used to be able to pass arrays into PHP function with ease and this is confusing me. It also seems I can't do this:
def someFunc(*args, someString)
As it throws up an error.
I think I've just got myself completely confused and looking for someone to clear it up for me.
When you define your function using this syntax:
def someFunc(*args):
for x in args
print x
You're telling it that you expect a variable number of arguments. If you want to pass in a List (Array from other languages) you'd do something like this:
def someFunc(myList = [], *args):
for x in myList:
print x
Then you can call it with this:
items = [1,2,3,4,5]
someFunc(items)
You need to define named arguments before variable arguments, and variable arguments before keyword arguments. You can also have this:
def someFunc(arg1, arg2, arg3, *args, **kwargs):
for x in args
print x
Which requires at least three arguments, and supports variable numbers of other arguments and keyword arguments.
You can pass lists just like other types:
l = [1,2,3]
def stuff(a):
for x in a:
print a
stuff(l)
This prints the list l. Keep in mind lists are passed as references not as a deep copy.
You don't need to use the asterisk to accept a list.
Simply give the argument a name in the definition, and pass in a list like
def takes_list(a_list):
for item in a_list:
print item
Python lists (which are not just arrays because their size can be changed on the fly) are normal Python objects and can be passed in to functions as any variable. The * syntax is used for unpacking lists, which is probably not something you want to do now.
def sumlist(items=[]):
sum = 0
for i in items:
sum += i
return sum
t=sumlist([2,4,8,1])
print(t)

Categories