Can I use a function passed by parameters? - python

I have a function, and inside this function I should execute another function of 3 posibilities.
The simple way should be passing a parameter, doing a if-elif to exec function acording to that parameter, but I'd like to know it it's posible to pass the name of a funtion by params and use that, something like:
FunctionA(Param1, Param2, FunctionNameToUse)
....Code....
FunctionNameToUse(Value1, Value2)
....Code....
endFunctionA
Depending on how functionA is called, it will use one Function or another, I dont know if I explained well...
Thanks mates!

Functions themselves are first class objects in Python. So there's no need to pass the name: pass the actual function itself, then you can call it directly.
def func1(a, b):
pass
def func2(a, b):
pass
def functionA(val1, val2, func):
func(val1, val2)
# now call functionA passing in a function
functionA("foo", "bar", func1)

In python, functions are first-class values, which means they can be passed around as arguments, returned from functions, and so on.
So the approach you want to take should work (However you're not passing the name, you're passing the actual function).
Take a look at map and filter in the standard library, they do exactly this.

Yes, you can. As other have mentioned, functions are first-class objects, i.e. you can do everything you can think of to it (see What are "first class" objects? for more info).
So then, how does this really work when you pass in a function as parameter? If you have taken any ComSci class, you'd know that each process has a special area in memory allocated for its code; all of your functions are defined here. Whenever you call a function, the CPU would move the Program Counter (a special pointer that points to whatever code it is executing at the moment) to the beginning of that function's code, and go from there. Thus, after the function is loaded in memory, all that's needed to call it is its address. When you pass a function A's "name" as an argument to another function B in Python, what you are doing is really passing a reference (in C term, a pointer) that contains the address to the code that represents A in memory.

Related

Python: calling a child function using a string

Does anyone know how to call a child function that belongs to a parent function using the dot operator, but where the child function's name is stored in a string variable.
def parent_function():
# do something
def child_function():
# do something else
Now imagine I have a string called 'child_function'. Is there a way to do this:
method_name = 'child_function'
parent_function.method_name()
I understand that method_name is a string and so it is not callable. The syntax above is clearly wrong, but I wanted to know if there was a way to do this?
Thank you!
As others have pointed out in comments there will need to be a little more setup to actually call an inner function, such as a parameter like this:
def parent_function(should_call=False):
# do something
def child_function():
print("I'm the child")
if should_call:
child_function()
That being said, and to answer your specific question, you technically can call the inner function directly. I should note this is bad and you should not be doing this. You can access the inner function via the outer function's code object
exec(parent_function.__code__.co_consts[1])
As opposed to many comments, you can actually access inner functions even if the outer function is not in the system memory anymore. This technique in python is called closure.
To know more about closure, visit Programiz
Coming to your requirement, you need to call the nested method outside the nesting function.
What are we leveraging?
Closure technique of python
locals() method which returns all the local properties and methods inside an enclosing method.
lambda x: x, A anonymous (Lambda) function
def parent_function():
# do something
def child_function():
# do something else
print("child_function got invoked")
return {i: j for i, j in locals().items() if type(j) == type(lambda x: x)}
# locals() returns all the properties and nested methods inside an enclosing method.
# We are filtering out only the methods / funtions and not properties / variables
parent_function()["child_function"]()
The below is the output.
>>> child_function got invoked
Better Solution:
Instead of using nested methods, leverage the concept of classes provided by Python.
Enclose the nested functions as methods inside a class.
If you include global child_function in parent_function, then once you run parent_function, you can call child_function in the main program. It's not a very clean way of defining functions, though. If you want a function defined in the main program, then you should define it in the main program.
Consider the following case:
def parent_function():
a = 1
Can you access a from the global scope? No, because it is a local variable. It is only existent while parent_function runs, and forgotten after.
Now, in python, a function is stored in a variable just like any other value. child_function is a local variable just like a. Thus, it is in principle not possible to access it from outside parent_function.
Edit: unless you make it available to the outside somehow, e.g. by returning it. But then, still the name child_function is internal to parent_function.
Edit 2: You can get functions given by name (as string) by using the locals() and globals() dictionaries.
def my_function():
print "my function!"
func_name = "my_function"
f = globals()[func_name]
f()

Passing a variable from one function to another function

I have a function with way to much going on in it so I've decided to split it up into smaller functions and call all my block functions inside a single function. --> e.g.
def main_function(self):
time_subtraction(self)
pay_calculation(self,todays_hours)
and -->
def time_subtraction(self):
todays_hours = datetime.combine(datetime(1,1,1,0,0,0), single_object2) - datetime.combine(datetime(1,1,1,0,0,0),single_object)
return todays_hours
So what im trying to accomplish here is to make todays_hours available to my main_function. I've read lots of documentation and other resources but apparently I'm still struggling with this aspect.
EDIT--
This is not a method of the class. Its just a file where i have a lot of functions coded and i import it where needed.
If you want to pass the return value of one function to another, you need to either nest the function calls:
pay_calculation(self, time_subtraction(self))
… or store the value so you can pass it:
hours = time_subtraction(self)
pay_calculation(self, hours)
As a side note, if these are methods in a class, you should be calling them as self.time_subtraction(), self.pay_calculation(hours), etc., not time_subtraction(self), etc. And if they aren't methods in a class, maybe they should be.
Often it makes sense for a function to take a Spam instance, and for a method of Spam to send self as the first argument, in which case this is all fine. But the fact that you've defined def time_subtraction(self): implies that's not what's going on here, and you're confused about methods vs. normal functions.

Python function with a lot of arguments

I am new to Python and higher level languages in general, so I was wondering if it is looked down upon if I have a function that takes in a lot of arguments, and how to better architect my code to prevent this.
For example what this function is essentially doing is printing each location of a string in a file.
def scan(fpin,base,string,pNo,print_to_file,dumpfile_path,quiet):
This function is being called from the main function, which is basically parsing the command line arguments and passing the data to the scan function. I have thought of creating a class containing all of these arguments and passing it to scan,but there will only be one instance of this data, so wouldn't that be pointless?
Named arguments are your friends. For things that act like semi-optional configuration options with reasonable defaults, give the parameters the defaults, and only pass them (as named arguments) for non-default situations. If there are a lot of parameters without reasonable defaults, then you may want to name all of them when you call the function.
Consider the built-in function sorted. It takes up to four arguments. Is the reverse parameter before or after cmp? What should I pass in as key if I want the default behavor? Answer: Hell if I can remember. I call sorted(A, reverse=True) and it does what I'd expect.
Incidentally, if I had a ton of "config"-style arguments that I was passing into every call to scan, and only changing (say, fpin and string) each time, I might be inclined to put all the other argumentsinto a dictionary, and then pass it to the function with **kwargs syntax. That's a little more advanced. See the manual for details. (Note that this is NOT the same as declaring the function as taking **kwargs. The function definition is the same, the only difference is what calls to it look like.)
No, there's really nothing wrong with it. If you have N different arguments (things that control the execution of your function), you have to pass them somehow - how you actually do that is just user preference if you ask me.
However... if you find yourself doing something like this, though:
func('somestring', a=A, b=B, c=C)
func('something else', a=A, b=B)
func('something third', a=A, c=C, d=D)
etc. where A,B,C are really configurations for lots of different things, then you should start looking into a class. A class does many things, but it does also create context. Instead, then you can do something like:
cf = myclass(a=A, b=B, c=C, d=D)
cf.func('somestring')
cf.func('something else')
cf.func('something third')
etc.

explicitly passing functions in python

Out of curiosity is more desirable to explicitly pass functions to other functions, or let the function call functions from within. is this a case of Explicit is better than implicit?
for example (the following is only to illustrate what i mean)
def foo(x,y):
return 1 if x > y else 0
partialfun = functools.partial(foo, 1)
def bar(xs,ys):
return partialfun(sum(map(operator.mul,xs,ys)))
>>> bar([1,2,3], [4,5,6])
--or--
def foo(x,y):
return 1 if x > y else 0
partialfun = functools.partial(foo, 1)
def bar(fn,xs,ys):
return fn(sum(map(operator.mul,xs,ys)))
>>> bar(partialfun, [1,2,3], [4,5,6])
There's not really any difference between functions and anything else in this situation. You pass something as an argument if it's a parameter that might vary over different invocations of the function. If the function you are calling (bar in your example) is always calling the same other function, there's no reason to pass that as an argument. If you need to parameterize it so that you can use many different functions (i.e., bar might need to call many functions besides partialfun, and needs to know which one to call), then you need to pass it as an argument.
Generally, yes, but as always, it depends. What you are illustrating here is known as dependency injection. Generally, it is a good idea, as it allows separation of variability from the logic of a given function. This means, for example, that it will be extremely easy for you to test such code.
# To test the process performed in bar(), we can "inject" a function
# which simply returns its argument
def dummy(x):
return x
def bar(fn,xs,ys):
return fn(sum(map(operator.mul,xs,ys)))
>>> assert bar(dummy, [1,2,3], [4,5,6]) == 32
It depends very much on the context.
Basically, if the function is an argument to bar, then it's the responsibility of the caller to know how to implement that function. bar doesn't have to care. But consequently, bar's documentation has to describe what kind of function it needs.
Often this is very appropriate. The obvious example is the map builtin function. map implements the logic of applying a function to each item in a list, and giving back a list of results. map itself neither knows nor cares about what the items are, or what the function is doing to them. map's documentation has to describe that it needs a function of one argument, and each caller of map has to know how to implement or find a suitable function. But this arrangement is great; it allows you to pass a list of your custom objects, and a function which operates specifically on those objects, and map can go away and do its generic thing.
But often this arrangement is inappropriate. A function gives a name to a high level operation and hides the internal implementation details, so you can think of the operation as a unit. Allowing part of its operation to be passed in from outside as a function parameter exposes that it works in a way that uses that function's interface.
A more concrete (though somewhat contrived) example may help. Lets say I've implemented data types representing Person and Job, and I'm writing a function name_and_title for formatting someone's full name and job title into a string, for client code to insert into email signatures or on letterhead or whatever. It's obviously going to take a Person and Job. It could potentially take a function parameter to let the caller decide how to format the person's name: something like lambda firstname, lastname: lastname + ', ' + firstname. But to do this is to expose that I'm representing people's names with a separate first name and last name. If I want to change to supporting a middle name, then either name_and_title won't be able to include the middle name, or I have to change the type of the function it accepts. When I realise that some people have 4 or more names and decide to change to storing a list of names, then I definitely have to change the type of function name_and_title accepts.
So for your bar example, we can't say which is better, because it's an abstract example with no meaning. It depends on whether the call to partialfun is an implementation detail of whatever bar is supposed to be doing, or whether the call to partialfun is something that the caller knows about (and might want to do something else). If it's "part of" bar, then it shouldn't be a parameter. If it's "part of" the caller, then it should be a parameter.
It's worth noting that bar could have a huge number of function parameters. You call sum, map, and operator.mul, which could all be parameterised to make bar more flexible:
def bar(fn, xs,ys, g, h, i):
return fn(g(h(i,xs,ys))
And the way in which g is called on the output of h could be abstracted too:
def bar(fn, xs, ys, g, h, i, j):
return fn(j(g, h(i, xs, ys)))
And we can keep going on and on, until bar doesn't do anything at all, and everything is controlled by the functions passed in, and the caller might as well have just directly done what they want done rather than writing 100 functions to do it and passing those to bar to execute the functions.
So there really isn't a definite answer one way or the other that applies all the time. It depends on the particular code you're writing.

How can this python function code work?

this is from the source code of csv2rec in matplotlib
how can this function work, if its only parameters are 'func, default'?
def with_default_value(func, default):
def newfunc(name, val):
if ismissing(name, val):
return default
else:
return func(val)
return newfunc
ismissing takes a name and a value and determines if the row should be masked in a numpy array.
func will either be str, int, float, or dateparser...it converts data. Maybe not important. I'm just wondering how it can get a 'name' and a 'value'
I'm a beginner. Thanks for any 2cents! I hope to get good enough to help others!
This with_default_value function is what's often referred to (imprecisely) as "a closure" (technically, the closure is rather the inner function that gets returned, here newfunc -- see e.g. here). More generically, with_default_value is a higher-order function ("HOF"): it takes a function (func) as an argument, it also returns a function (newfunc) as the result.
I've seen answers confusing this with the decorator concept and construct in Python, which is definitely not the case -- especially since you mention func as often being a built-in such as int. Decorators are also higher-order functions, but rather specific ones: ones which return a decorated, i.e. "enriched", version of their function argument (which must be the only argument -- "decorators with arguments" are obtained through one more level of function/closure nesting, not by giving the decorator HOF more than one argument), which gets reassigned to exactly the same name as that function argument (and so typically has the same signature -- using a decorator otherwise would be extremely peculiar, un-idiomatic, unreadable, etc).
So forget decorators, which have absolutely nothing to do with the case, and focus on the newfunc closure. A lexically nested function can refer to (though not rebind) all local variable names (including argument names, since arguments are local variables) of the enclosing function(s) -- that's why it's known as a closure: it's "closed over" these "free variables". Here, newfunc can refer to func and default -- and does.
Higher-order functions are a very natural thing in Python, especially since functions are first-class objects (so there's nothing special you need to do to pass them as arguments, return them as function values, or even storing them in lists or other containers, etc), and there's no namespace distinction between functions and other kinds of objects, no automatic calling of functions just because they're mentioned, etc, etc. (It's harder - a bit harder, or MUCH harder, depending - in other languages that do draw lots of distinctions of this sort). In Python, mentioning a function is just that -- a mention; the CALL only happens if and when the function object (referred to by name, or otherwise) is followed by parentheses.
That's about all there is to this example -- please do feel free to edit your question, comment here, etc, if there's some other specific aspect that you remain in doubt about!
Edit: so the OP commented courteously asking for more examples of "closure factories". Here's one -- imagine some abstract kind of GUI toolkit, and you're trying to do:
for i in range(len(buttons)):
buttons[i].onclick(lambda: mainwin.settitle("button %d click!" % i))
but this doesn't work right -- i within the lambda is late-bound, so by the time one button is clicked i's value is always going to be the index of the last button, no matter which one was clicked. There are various feasible solutions, but a closure factory's an elegant possibility:
def makeOnclick(message):
return lambda: mainwin.settitle(message)
for i in range(len(buttons)):
buttons[i].onclick(makeOnClick("button %d click!" % i))
Here, we're using the closure factory to tweak the binding time of variables!-) In one specific form or another, this is a pretty common use case for closure factories.
This is a Python decorator -- basically a function wrapper. (Read all about decorators in PEP 318 -- http://www.python.org/dev/peps/pep-0318/)
If you look through the code, you will probably find something like this:
def some_func(name, val):
# ...
some_func = with_default_value(some_func, 'the_default_value')
The intention of this decorator seems to supply a default value if either the name or val arguments are missing (presumably, if they are set to None).
As for why it works:
with_default_value returns a function object, which is basically going to be a copy of that nested newfunc, with the 'func' call and default value substited with whatever was passed to with_default_value.
If someone does 'foo = with_default_value(bar, 3)', the return value is basically going to be a new function:
def foo(name, val):
ifismissing(name, val):
return 3
else:
return bar(val)
so you can then take that return value, and call it.
This is a function that returns another function. name and value are the parameters of the returned function.

Categories

Resources