Python inner function runtime complexity - python

Suppose I wrote a function to create another function, say like:
def g(x):
#do stuff
def h(y):
return x*y
return h
my_func = g(10)
for i in range(100):
print(my_func(i))
In my for loop I am calling my_func a hundred times, however since I only call g once to create my_func I would expect that the #do stuff bit of my code will only run once at the beginning and not once every iteration of the loop.
Can anyone confirm that this is actually the case or will it run every single time inside the for loop? I couldn't find a satisfactory answer elsewhere.

Correct, if there was a line of code where #do stuff is, it would only run once in this example.
Tip: if you had replaced it with print("test") you could have checked this for yourself.

Related

Changing function name every time script runs

I have a for loop running in a script, and in that for loop there is a function, def OpenButton():, which triggers when a tkinter button is pressed (although this has nothing to do with tkinter). I need the name of the def script to have a different string at the end, every time the for loops runs.
Example: First loop: def OpenButtonString1(): but the second time it runs to be def OpenButtonString2(): (They would be actual strings, not def OpenButtonString increasing number ():, but I can't figure it out, since using exec('def OpenButton' + StringName + '():') doesn't actually detect the indented lines under as something part of the function.
What you need is a function that returns functions. The name of a function isn't really that important.
>>> def function_creator(foo):
... def dynamic_function():
... print(foo)
... return dynamic_function
...
>>> func1 = function_creator('Hello')
>>> func2 = function_creator('World')
>>> func1()
Hello
>>> func2()
World
You can store the functions just like any other variable, like putting them in a list or dictionary. Also, as you can see in my example, you can pass whatever information you need into your function creator and the function it creates can use the info upon being called.

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'

Python: How to return data more that once during a function call

Is there any way that a function can be called once and then return data mutliple times at distinct times?
For example, suppose I had the following code:
def do_something():
for i in range(1, 10):
return 1
However, I want to be able to return more than one piece of data from a single function call, but at asynchronous times, is this possible?
For context, I have a program that generates word documents, converts them into pdfs and then combines them into a single pdf document. I want to be able to call an external function from the GUI to create the documents, and then display a progress bar that displays the current progress through the function.
Edit:
I am already aware of the yield function. I thought my specific problem at the bottom of the question would help. To be clearer, I am looking for is a way to return multiple values from a function and cause a different event for each value returned. Although it may be a poor example, what I want is to be able to do is something similar to a .then(){} in Javascript, but be able to perform the .then(){} using multiple returned values
yield is the thing as mentioned by almost everyone for returning or getting multiple values from a function.
Having read your problem statement. Here is the solution I would devise for you.
Create a function to update status bar, the value of status bar would be fetched from a global variable. So global x=0 at starting, and in the update function it will first update the x = x+1 then after that it will increment the status bar.
def do_something():
for i in range(1, 10):
# fetch and perform operation on that Doc for PDF
update_status_bar()
You want a generator:
def do_something():
for i in range(1,10):
yield i
nums = do_something()
Each time you call next on nums, the body of do_something will continue executing up to the next yield statement, at which point it returns that value.
>>> print next(nums) # Outputs 1
>>> print next(nums) # Outputs 2
>>> ...
You are looking for generators.
Instead of returning you yield (read What does the "yield" keyword do in Python?) from your function.
def do_something():
for i in range(1, 10):
yield i
If you want this function to be called repeatedly you will need to have a wrapper that calls this function repeatedly. Somewhat similar to:
def worker():
for i in do_something():
UpdateProgress(i)
sleep(prgressInterval)
thread = Thread(target=worker)
thread.start()

Understanding Python Twisted Looping Call - Save the return of the LoopingCall function

I am using Twisted and making a Looping Call every x seconds.
The function I use for the looping calls makes a return statement.
def f():
# Obtain stuff
return stuff
def main():
LoopingCall(f).start(x)
How can I retrieve the return result of f?
Thanks!
Where do you want to "retrieve" the result of f from? LoopingCall is just called by the reactor, so this question doesn't really make sense. If you want main to somehow access the result that doesn't make sense, because main is run once, but f is run a potentially unlimited number of times.
So perhaps you just want to do this, instead:
def f():
# Obtain stuff
return stuff
def do_something_with_f():
result = f()
do_something(result)
def main():
LoopingCall(do_something_with_f).start(x)

Python custom function

I have been working at learning Python over the last week and it has been going really well, however I have now been introduced to custom functions and I sort of hit a wall. While I understand the basics of it, such as:
def helloworld():
print("Hello World!")
helloworld()
I know this will print "Hello World!".
However, when it comes to getting information from one function to another, I find that confusing. ie: function1 and function2 have to work together to perform a task. Also, when to use the return command.
Lastly, when I have a list or a dictionary inside of a function. I'll make something up just as an example.
def my_function():
my_dict = {"Key1":Value1,
"Key2":Value2,
"Key3":Value3,
"Key4":Value4,}
How would I access the key/value and be able to change them from outside of the function? ie: If I had a program that let you input/output player stats or a character attributes in a video game.
I understand bits and pieces of this, it just confuses me when they have different functions calling on each other.
Also, since this was my first encounter with the custom functions. Is this really ambitious to pursue and this could be the reason for all of my confusion? Since this is the most complex program I have seen yet.
Functions in python can be both, a regular procedure and a function with a return value. Actually, every Python's function will return a value, which might be None.
If a return statement is not present, then your function will be executed completely and leave normally following the code flow, yielding None as a return value.
def foo():
pass
foo() == None
>>> True
If you have a return statement inside your function. The return value will be the return value of the expression following it. For example you may have return None and you'll be explicitly returning None. You can also have return without anything else and there you'll be implicitly returning None, or, you can have return 3 and you'll be returning value 3. This may grow in complexity.
def foo():
print('hello')
return
print('world')
foo()
>>>'hello'
def add(a,b):
return a + b
add(3,4)
>>>7
If you want a dictionary (or any object) you created inside a function, just return it:
def my_function():
my_dict = {"Key1":Value1,
"Key2":Value2,
"Key3":Value3,
"Key4":Value4,}
return my_dict
d = my_function()
d['Key1']
>>> Value1
Those are the basics of function calling. There's even more. There are functions that return functions (also treated as decorators. You can even return multiple values (not really, you'll be just returning a tuple) and a lot a fun stuff :)
def two_values():
return 3,4
a,b = two_values()
print(a)
>>>3
print(b)
>>>4
Hope this helps!
The primary way to pass information between functions is with arguments and return values. Functions can't see each other's variables. You might think that after
def my_function():
my_dict = {"Key1":Value1,
"Key2":Value2,
"Key3":Value3,
"Key4":Value4,}
my_function()
my_dict would have a value that other functions would be able to see, but it turns out that's a really brittle way to design a language. Every time you call my_function, my_dict would lose its old value, even if you were still using it. Also, you'd have to know all the names used by every function in the system when picking the names to use when writing a new function, and the whole thing would rapidly become unmanageable. Python doesn't work that way; I can't think of any languages that do.
Instead, if a function needs to make information available to its caller, return the thing its caller needs to see:
def my_function():
return {"Key1":"Value1",
"Key2":"Value2",
"Key3":"Value3",
"Key4":"Value4",}
print(my_function()['Key1']) # Prints Value1
Note that a function ends when its execution hits a return statement (even if it's in the middle of a loop); you can't execute one return now, one return later, keep going, and return two things when you hit the end of the function. If you want to do that, keep a list of things you want to return and return the list when you're done.
You send information into and out of functions with arguments and return values, respectively. This function, for example:
def square(number):
"""Return the square of a number."""
return number * number
... recieves information through the number argument, and sends information back with the return ... statement. You can use it like this:
>>> x = square(7)
>>> print(x)
49
As you can see, we passed the value 7 to the function, and it returned the value 49 (which we stored in the variable x).
Now, lets say we have another function:
def halve(number):
"""Return half of a number."""
return number / 2.0
We can send information between two functions in a couple of different ways.
Use a temporary variable:
>>> tmp = square(6)
>>> halve(tmp)
18.0
use the first function directly as an argument to the second:
>>> halve(square(8))
32.0
Which of those you use will depend partly on personal taste, and partly on how complicated the thing you're trying to do is.
Even though they have the same name, the number variables inside square() and halve() are completely separate from each other, and they're invisible outside those functions:
>>> number
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
NameError: name 'number' is not defined
So, it's actually impossible to "see" the variable my_dict in your example function. What you would normally do is something like this:
def my_function(my_dict):
# do something with my_dict
return my_dict
... and define my_dict outside the function.
(It's actually a little bit more complicated than that - dict objects are mutable (which just means they can change), so often you don't actually need to return them. However, for the time being it's probably best to get used to returning everything, just to be safe).

Categories

Resources