Python lambda return value - python

I'm learning the lambda options to return in python and i have a question:
I need to fill the returns in this function:
def func(n):
if n==0:
print("finished")
else:
return ___
func(5)()()()()()
func(3)()()()
func(8)()()()()()()()()
The output:
finished
finished
finished
I thought this one is a recursive call like return func(n-1) but it doesn't work, and throws an error.
Is there an option to overcome the extra empty brackets? count them? do something, because it should be runnable.
Thanks

You're right about needing to use lambdas and func n-1, specifically
return lambda: func(n-1)
This returns a lambda that doesn't need any parameters passed in, to handle the brackets, and the return of the is the function being called with n-1, which in most calls you're making, is returning the next lambda function call

The operator () is the function call.
So for example:
def foo():
print('Foo executed')
def bar():
# We return the foo FUNCTION itself, without calling it.
return foo
In the above code, if you execute foo(), it'll print "Foo executed". But if you execute bar(), it will return foo, which is the function. So you can execute bar()(), where the first () is executing the function bar, returning foo, and then with the second (), you call the returned foo function.
Edit: When I typed it, you removed the what are those bunch of () because they are new to you... But I just leave it there maybe it'll help.

Related

When I decorate a function why the original function becomes none type

def outer_fun(func):
print('outer function ran')
def inner_function():
print('inner function ran')
return func()
return inner_function()
def fun():
print("Hi")
fun = outer_fun(fun)
print(fun)
the output is:
outer function ran
inner function ran
Hi
None
why the none here?
when I do
fun = outer_fun(fun)
and calls it immediately inside the inner_function it runs fun() and makes the fun a none object? why?
Also if I try to run fun = outer_fun(fun) again it says object is not callable
In a simple word your None is occur for this code
def fun():
print("Hi")
because its return Nothing, if you return something then it can show this instead of None. If you don't want to see None then use fun instead of print(fun).
fun() implicitly returns None. So when you set
fun = outer_fun(fun)
you have set fun to None. Before that assignment, fun is a function.
When you repeat that call, fun is already None, so you are doing this:
fun = outer_fun(None)
which as you note fails because None is not callable.
From the subject of your question, it seems you are trying to write a decorator. Your decorator has to return a function (typically an inner function or closure). If your decorator doesn't return anything, then you'll probably see the behavior you are trying to understand.
Your outer function ends with:
return inner_function()
which should be:
return inner_function
ie: return the function, not call the function and return whatever it returns.

When is a function called/referred to and when is it being executed?

I'm relatively new to Python and I have a (I guess) pretty basic question on functions in Python.
I'm rewatching basics tutorials in order to really understand more of the structures and not just use them. I used some basic code from a tutorial and tried different simple variations and I don't fully understand the outcomes and when a function is being referred to, i.e. when its return value is being called for, and when it's being executed.
x=6
def example():
globx = x
print(globx)
globx+=5
print(globx)
example()
This defines the function and afterwards calls for it to be executed and as it's being executed it prints 6 and then prints 11, as expected.
Now:
x=6
def example():
globx = x
print(globx)
globx+=5
print(globx)
print(example())
I would have expected this to print "None" since print is looking for a return value of the function to print it but example() doesn't return a value. Instead 6, 11 and None are being printed. So I assume print(example()) calls for example()'s return value to print it but before also executes the function. (Please correct me if I got that wrong.).
Even when I'm just assigning the return value to a variable x = example() after the definition of the function, it will also execute the function and print 6 and then 11.
x=6
def example():
globx = x
print(globx)
globx+=5
print(globx)
x = example()
Is a function always being executed when it's written out? (Ecxcept in the def)
Is there a way to make use of a functions return value without it being fully executed?
For example if I had a more complex code and at some point I want to make use of a functions return value but don't want it to be run.
Thanks in advance!
What you say seems overall correct, even if it seems off what you expected.
Generally, you can see it as, when the function has parentheses at the end, i.e. example(), the function is executed.
Your last question is a bit vague, but you can stop executing the function at some point by using the return keyword inside the function. This makes sense in e.g. a function that performs some resource-intensive calculations, but occasionally there's a chance to take a shortcut.
As an example
def calculate_thing(shortcut = False):
if shortcut:
return 3
# Resource-intensive, time-consuming calculations go here
return result_of_calculations
Calling this function with calculate_thing(shortcut=True) will quickly return 3, because the function stops executing when we hit return 3. On the other hand, calling it by calculate_thing(shortcut=False) or calculate_thing() (False is the default value for shortcut) will make the function run for a while, doing some calculations, and then it returns whatever value was assigned to the variable result_of_calculations.
You are getting confused by what a function returns and what a function does.
In your case you have a function which has two print() statements. Those statements have nothing to do with the value that the function will return and will print their corresponding values on every invocation of the function example().
The return value of the function is defined using the return keyword and if it is not defined then it is None. Obviously the function needs to be executed in order to get it to return a value.
A function does something, it literally performs a function. If you want that function to show you results as it's doing its job, you can print() things. If you just want it to do its job and save the results for later, you return them to a variable that calls the function. You can do both!
def just_print(input):
print('Here is a function printing!', input)
just_print('cool!')
>> 'Here is a function printing!', 'cool!'
def return_value(input):
return 'Hello ' + input
# We can store the return for future use
save_return_val = return_value('Ari')
print(save_return_val)
>> 'Hello Ari'
# Just print it
print(return_value('Ari'))
>> 'Hello Ari'

Decorating Functions

I'm a python beginner and I struggle with a somewhat easy concept of functional programming. I simply can not see why the nested function (see example below) would even be called. This is quite hard to explain.
func3 = func1(func2)
Here I call func1 with the positional argument func2. All fair and well. func1 returns a nested function. But when I run the code the function nest1has been executed even though I've only called func1 (I dont see why this should execute the nested function). func1 should not do more than returning a function without printing anything. Can someone explain this to me?
def func2():
def nest2():
print('Nest2')
nest2()
return nest2
def func1(func):
def nest1():
print('Nest1')
func()
return nest1
func3 = func1(func2)
func3()
If I call a simple function with a nested function the inner function is not executed. See below:
def new_func():
def inner():
print(1)
return inner
new_func()
func1() returns the method nest1 (without executing it), so your call func3 = func1(func2) returns nest1 and assigns it to func3.
The next line you are executing whatever is assigned to func3 - which is the method nest1. In other words, the line func3() is executing the function nest1, and causing the text to print.
But when I run the code the function nest1 has been executed even though I've only called func1 (I dont see why this should execute the nested function). Func 1 should not do more than returning a function without printing anything. Can someone explain this to me?
When you do this:
func3 = func1(func2)
You pass the function func2 into the function func1. Inside of func1, you define a function nest1 that calls the function passed in. This function is then returned and becomes the value of func3. The only thing func1 does is create the nest1 function, and return it. When func3 is called, you actually called the function defined inside of func1, nest1.
If I call a simple function with a nested function the inner function is not executed.
The reason your second example did not work as expected, is because calling new_func does not call inner, it only creates inner and returns it. This is the same case as above. Calling func1 did not call nest1, it simply created nest1 and returned it. You had to explitly call nest1 (func3()). Likewise, you need to call the function returned from new_func explicitly:
new_func()()
In the final example, you need to call the function that is being returned with an extra ():
def new_func():
def inner():
print(1)
return inner
new_func()()
Output:
1
Body of func2 is:
def nest2():
print('Nest2')
nest2()
return nest2
And so body of func1(func2) is:
print('Nest1')
def nest2():
print('Nest2')
nest2()
return nest2
The last piece we get by replacing func with body of func2 in body of nest1.

Python basic nested statements and scope concept

def func():
def nested():
global x
x = 1
x = 2
func()
print(x)
The correct answer would be '2' and the reason why is because func() is not defined. But when I read this it seems that func() is defined as nested(). I would think that when you call func() that would then automatically call nested(). I'm struggling to grasp this and understand why I shouldn't read it that way.
You're defining nested inside func, but you're not calling nested() anywhere in func, so when you call func() it's effectively doing nothing.
To do what you want try defining func as:
def func():
def nested():
global x
x = 1
nested()
UPDATE: After StevenRumbalski's comment, I think a small addition about what exactly is going on in that function can help clarify things around.
Python's functions are themselves objects which can respond to the operator ().
When you define a new function, what you're actually doing is instantiating a function object and giving it a name. In the example above, def func() creates a function instance and gives it name func, so that when you apply operator () to func (i.e. when you call the function with func()) the code of the function associated to that name is executed.
Let's now take one step further and look at what happens with nested.
Nested is defined inside func's scope, so when you exit func's scope the name nested is not defined anymore.
If, however, you return the function object to the caller of func, you can use that object to run nested's code.
A small example:
def returning_func():
def nested():
print("I am nested!")
return nested # note the lack of the () operator!
In this case, if we do
my_reference_to_nested = func()
nothing gets printed, because nested is defined but not executed.
If we call it, however:
my_reference_to_nested()
we execute nested's code and print to the output I am nested!

decorator in python invocation sequence

I am trying write a decorator in python 3 which basically keeps a count on the number of times a function gets called.
Here is my code:
def call_counter(func):
def helper(x):
helper.calls += 1
return func(x)
helper.calls = 0
return helper
#call_counter
def succ(x):
return x + 1
for i in range(10):
print(succ(i)) # <--- ??
I understand how decorator works but only confusion I have here is that the first ever call to succ(x) gets a function in return #call_counter decorator.
However the main confusion here is I dont quite understand how sequential calls inside the for loop happens here?
So how does the flow go after we have a returned function (helper in this case) from first call.
Now inside the for loop, succ(0), succ(1) and so on gets called, how does that work? Do we reuse the same returned function that we got from the first call or does decorator gets called everytime the for loop gets added by 1?
The decorator is applied only once when it is met and after that all invocations of succ use the same function you've returned helper.
This can be seen if you just printed the function object inside the for loop instead of calling it:
for i in range(10):
print(succ)
<function call_counter.<locals>.helper at 0x7fe4d05139d8>
<function call_counter.<locals>.helper at 0x7fe4d05139d8>
# ... so on, ten times.
The flow is straight-forward, helper is called each and every time with the argument x which is passed to func.

Categories

Resources