why this code is printing once "potato" instead than 5 times ?
def print_word(word):
print word
return
def do_n(function , n):
for i in range(n):
function
return
do_n( print_word("potato") , 5 )
Your code is actually not passing print_word("potato") ("the 'call' to the print_word") to do_n, but instead it's passing None since print_word returns None. Which means that the only time that print_word ran was at do_n( print_word("potato") , 5 ). What you can do instead is use functools.partial, which returns a function with the args applied to it:
from functools import partial
def print_word(word):
print(word)
return # side note: the "return" isn't necessary
def do_n(function , n):
for i in range(n):
function() # call the function
return
do_n( partial(print_word,"potato") , 5)
functools.partial:
Return a new partial object which when called will behave like func
called with the positional arguments args and keyword arguments
keywords. If more arguments are supplied to the call, they are
appended to args.
Another way is to use a lambda statement or pass the argument separately:
def print_word(word):
print(word)
return # side note: the "return" isn't necessary
def do_n(function , n):
for i in range(n):
function() # call the function
return
do_n(lambda: print_word("potato"), 5) # use the lambda
Or:
def print_word(word):
print(word)
return # side note: the "return" isn't necessary
def do_n(function , n, *args):
for i in range(n):
function(*args) # call the function
return
do_n(print_word, 5, "potato") # pass the argument of print_word as a separate arg
To pass a function with arguments, you can either pass the arguments separately, or you can do a 'partial' application of the function, where you lock a number of variables. Here is such as solution to your problem, where I have 'partially' applied all variables. But, the function is still not called until the function() statement.
from functools import partial
def print_word(word):
print word
return
def do_n(function, n):
for i in range(n):
function()
return
print_potato = partial(print_word, potato)
do_n(print_potato, 5)
Related
Trying to learn Python from the Think Python book and at the section about recursive functions.
An exercise there made me wonder how to call a function with arguments using another function generically.
The answer to the exercise itself is already available in another thread, but all solutions involve modifying the third function do_n() to add additional arguments that will match the second function print_n()
def countdown(n): # FIRST FUNCTION
if n <= 0:
print("blastoise")
else:
print(n)
countdown(n-1)
def print_n(s, n): # SECOND FUNCTION
if n <=0:
return
print(s)
print_n(s, n-1)
def do_n(f, s, n): # THIRD FUNCTION
if n <= 0:
return
f(s, n)
do_n(f, s, n-1)
How do you write the third function so that it is generic and works to call either the first function or second function or any other function by prompting you to enter the arguments for the called function instead of the solution above?
Thanks!
How do you write the third function so that it is generic and works to call either first function or second function or any other function by prompting you to enter the arguments ...?
I don't know where it would be useful to have the arguments entered by the user, but since you ask for it:
def do_in(f, n): # prompt to enter arguments, call f n times
try: a = eval(input('comma separated arguments: '))
except SyntaxError: a = () # you may want more sophisticated error checks
if not isinstance(a, tuple): a = a, # make single argument iterable
for _ in range(n): f(*a) # unpack arguments with starred expression
I'm newbie in Python, but the second time I encouter this problem.
Problem:
In some libraries there are functions with arguments. Sometimes there is argument as function, like this:
def somefun(fun):
x = [1,2,3]
z = fun(x)
return z
And I want to pass there some other function like this:
def func(x,y):
return x*y
which have more than one argument. I want to make one argument static, so somefun except func as argument.
Finally I want to make some kind of cycle where I can change static arg.
Something like this:
for i in xrange(1,9):
somefun(func(i,*))
Please do not offer me to change any functions. They are from library and it's not very comfortable to change them.
Thanks a lot!
You can use lambda statement:
somefun(lambda x: func(i, x))
It sure sounds like you are looking for functools.partial. From the docs:
functools.partial(func, *args, **keywords)
Return a new partial object which when called will behave like func called with the positional arguments args and keyword arguments keywords.
In your example, you could pass partial(func, 10) as the argument to somefun. Or you could create the partial objects and use them in a loop:
for i in xrange(1,9):
somefun(partial(func, i))
My solution with decorator
from functools import wraps
import numpy as np
def p_decorate(f):
#wraps(f)
def wrapped(*args):
z = f(*args)
return z
return wrapped
#p_decorate
def myfunc(a,b):
"""My new function"""
z = np.dot(a,b)
return z
x = [1,2,3]
y = [4,2,0]
r = myfunc(x,y)
print (r)
print (myfunc.__name__)
print (myfunc.__doc__)
You can change myfunc as you wish.You can also insert more function layers.Without the use of this decorator factory,you would lose the name of myfunc and the docstring.
I wanted to practice recursive and decorators and try to do this simple function but it doesn't work:
def dec(func):
def wrapper(number):
print("Recursive count:")
rec_cou(number)
return wrapper
#dec
def rec_cou(number):
""" Count from 0 to a given number from 50 and up """
if number == 0:
print(number)
return number
num = rec_cou(number - 1)
print(num + 1)
return num + 1
rec_cou(53)
The recursive function alone works well, but when i add the decorator generates error: maximun recursion depth exceeded
There are two problems with your decorator:
You try to call the decorated function, effectively invoking the wrapper function again inside the decorator, thus you have an infinite recursive loop; call the original function func instead.
To the outside, the decorated function should behave just like the original function, particularly it should return its result; otherwise you will get type errors for trying to add numbers and None
Also, currently your decorator is not counting anything... try this:
def dec(func):
func.count = 0 # give each decorated function its own counter
def wrapper(number):
print("Recursive count: %d" % func.count)
func.count += 1 # increase counter
return func(number) # call original function 'func' and return result
return wrapper
Update: From your comments, it seems I misunderstood what your decorator is supposed to do, and you misunderstood how decorators work. The decorator is not called once when you first call the function, but it replaces the function with the one defined within the decorator. In other words,
#dec
def foo(...):
...
is equivalent to
def foo(...):
...
foo = dec(foo)
I.e. the decorator in invoked exactly once when the function is decorated, and the function constructed in the decorator is called each time the original function is called, replacing it. If you want to print only once, either use the decorator from the other answer, or rather use no decorator at all: Just create a wrapper that prints and then calls the function. This is not unusual for providing an 'entry point' to recursive functions.
def print_and_run(number):
print("Recursive count:")
rec_cou(number)
BTW, this is the decorator that I usually use to visualize recursive calls:
def trace(f):
trace.depth = 0
def _f(*args, **kwargs):
print " " * trace.depth, ">", f.__name__, args, kwargs
trace.depth += 1
res = f(*args, **kwargs)
trace.depth -= 1
print " " * trace.depth, "<", res
return res
return _f
To solve the maximum recursion depth problem, call the function passed into the decorator (func) rather than rec_cou and return the value of the function call. That is, on line 5, replace rec_cou(number) with return func(number).
Edit:
def decorate(function):
def wrapper(parameter):
if wrapper.initial:
print("Recursive count:")
wrapper.initial = False
result = function(parameter)
wrapper.initial = True
return result
wrapper.initial = True
return wrapper
#decorate
def count(number):
""" Prints integers on the interval [0, number] """
if number:
count(number - 1)
print(number)
count(53)
Without decorator:
def count(number):
""" Prints integers on the interval [0, number] """
if number:
count(number - 1)
else:
print("Recursive count:")
print(number)
count(53)
If all you want is for the function rec_cou to print something before its recursive descent, just modify that function and don't bother with decorators.
def rec_cou(number, internal_call=False):
""" Count from 0 to a given number from 50 and up """
if not internal_call:
print "Now performing recursive count, starting with %d" % number
if number == 0:
return number
num = rec_cou(number - 1, internal_call=True)
return num + 1
As I mentioned in my comments, all I've done is take the idea behind Joel's answer (which was to add a variable--which I called a "flag"--indicating whether the function is being called externally or as part of the recursion) and moved the flag variable (which I've called internal_call, whereas Joel called it initial) inside the function itself.
Additionally, I'm not sure what all this num business is about. Note that:
For the 0 case, rec_cou returns 0.
For number > 0, num is set to the value returned by rec_cou(number-1), then 1+num is returned.
For example, in the case of rec_cou(1), num is set to rec_cou(0), which is 0, then 0 + 1 is returned, which is 1. Similarly, for rec_cou(2), one more than the value of rec_cou(1) is returned, so 2 is returned.
In short, for every natural number, rec_cou(number) returns the value of the input number. It's not clear what you're trying to achieve, but what you've got is an identity function, which seems unlikely to be what you want.
I want to define a function that takes some arguments as input, and uses them to make another function, then outputs the new function.
For example:
makeIncrease(n) --> return a function that takes an argument, and return (argument + n)
applyIncrease(increaseFn, m) --> will apply increaseFn to argument m
So if I do this: applyIncrease(makeIncrease(n), m) --> will return m+n
How can I do it in python?
You can read about decorators in Python for more on this. For your specific question:
def applyIncrease(increaseFn, m):
return increaseFn(m)
def makeIncrease(n):
def _innerFn(arg):
return arg + n
return _innerFn
applyIncrease accepts a function and argument, and applies the function to the argument.
makeIncrease accepts an argument n.
Let's say n=2 for the sake of an example. makeIncrease(2) returns a function that takes an argument and adds 2 to it.
Although I began _innerFn with an underscore, this is only a convention - the underscore is not required for the decorator to work.
Note also that functions are first class objects in Python, and that makeIncrease returns _innerFn and not _innerFn(). Return functions exactly as you would variables or object references - no parentheses.
Here are your functions in the interpreter. Note that the object reference wrapped_function refers to _innerFn, i.e. the return value of makeIncrease(2)
>>> wrapped_function = makeIncrease(2)
>>> wrapped_function
<function _innerFn at 0x100496758>
>>> total = applyIncrease(wrapped_function, 3)
>>> total
5
class Example:
def result():
def nestedResult(a,b):
multiply = a*b
return multiply
return nestedResult
if __name__ == "__main__":
x = result()
print "multiplication_result:", x(1,10)
This question already has answers here:
Python function as a function argument?
(10 answers)
Closed last month.
I am solving a puzzle using python and depending on which puzzle I am solving I will have to use a special set of rules. How can I pass a function into another function in Python?
Example
def Game(listA, listB, rules):
if rules == True:
do...
else:
do...
def Rule1(v):
if "variable_name1" in v:
return False
elif "variable_name2" in v:
return False
else:
return True
def Rule2(v):
if "variable_name3" and "variable_name4" in v:
return False
elif "variable_name4" and variable_name1 in v:
return False
else:
return True
This is just a pseudo code and therefore not specific but I get the code to compile but I need to know how to call the function Game and whether it's correctly defined since rules will be switched for either Rule1(v) or Rule2(v).
Just pass it in like any other parameter:
def a(x):
return "a(%s)" % (x,)
def b(f,x):
return f(x)
print b(a,10)
Treat function as variable in your program so you can just pass them to other functions easily:
def test ():
print "test was invoked"
def invoker(func):
func()
invoker(test) # prints test was invoked
For passing both a function, and any arguments to the function:
from typing import Callable
def looper(fn: Callable, n:int, *args, **kwargs):
"""
Call a function `n` times
Parameters
----------
fn: Callable
Function to be called.
n: int
Number of times to call `func`.
*args
Positional arguments to be passed to `func`.
**kwargs
Keyword arguments to be passed to `func`.
Example
-------
>>> def foo(a:Union[float, int], b:Union[float, int]):
... '''The function to pass'''
... print(a+b)
>>> looper(foo, 3, 2, b=4)
6
6
6
"""
for i in range(n):
fn(*args, **kwargs)
Depending on what you are doing, it could make sense to define a decorator, or perhaps use functools.partial.
Just pass it in, like this:
Game(list_a, list_b, Rule1)
and then your Game function could look something like this (still pseudocode):
def Game(listA, listB, rules=None):
if rules:
# do something useful
# ...
result = rules(variable) # this is how you can call your rule
else:
# do something useful without rules
A function name can become a variable name (and thus be passed as an argument) by dropping the parentheses. A variable name can become a function name by adding the parentheses.
In your example, equate the variable rules to one of your functions, leaving off the parentheses and the mention of the argument. Then in your game() function, invoke rules( v ) with the parentheses and the v parameter.
if puzzle == type1:
rules = Rule1
else:
rules = Rule2
def Game(listA, listB, rules):
if rules( v ) == True:
do...
else:
do...