def prefix_factory(prefix):
def prefix_printer(text):
print(f"{prefix}: {text}")
return prefix_printer
Now lets execute the below line.
# First time we are executing this
debug = prefix_factory('DEBUG')
# Second time we are executing as
debug('Hello world')
First time we are executing this
1st execution or assignment of function to the variable debug is assigned the value "DEBUG". My understanding is this is how it has to be executed.
ideally inner function prefix_printer(text) - gets defined inside prefix_factory()
'return prefix_printer' should get an error, stating that text is not available or text is missing.
Second time we are executing as
debug('hello world ') - 2nd execution of the function reference.
The question for the second execution is, I am assuming 'hello world' should be considered as a value for the prefix. and text should be blank as we don't call prefix_printer in the return statement with any value. Hence it has to be '' empty string. I am coming from c, C++ background.
My question is, it's the same piece of code 1st-time prefix is assigned,
but during the 2nd execution debug('Hello world') it behaves differently. How is it possible, please clarify in detail how this works?
When debug = prefix_factory('DEBUG') is executed, variable debug is assigned the return value from calling function prefix_factory('DEBUG'). It is not assigned the value "DEBUG" as you said. And what is this return value?
Function prefix_factory returns prefix_printer, which is a function nested within prefix_factory. Moreover, prefix_printer references a variable, prefix, which is defined in the outer, enclosing function. When prefix_factory returns a nested function, prefix_printer, that references a variable defined in the nesting function, that returned function is known as a closure. Even though we have now returned from the call to printing_factory, the closure function prefix_printer, which has now been assigned to variable debug, still has a reference to the value of variable prefix as it existed at the time prefix_factory was called.
Subsequently, when you execute debug('Hello World'), because debug evaluates to our prefix_printer closure , this is equivalent to calling function prefix_printer('Hello World') with variable prefix initialized to 'DEBUG'.
Related
So I have a function that returns a value. I'd like it to write it into shell only when called with print.
So c.function() doesn't return anything, while print(c.function) returns the value I need
Edit: I probably worded the question wrong
I have a class function that goes over an iterable, performs different tasks based on elements of the iterable. After completing the tasks it returns a number of the tasks completed. I need the function to write into shell only when called as print(c.function(iterable)), and to show nothing when called as c.function(iterable), is that possible?
Thanks in advance
If you write a function like,
def foo():
a = "This works."
return a
then call the function in the script like
foo()
nothing gets printed.
However, if you assign the function return call to a variable like
b = foo()
and print(b), then you get the result printed.
Simply assign to a dummy variable when you want to hide the output:
>>> _ = c.function()
And call the function normally when you want to view the output:
>>> c.function()
'the value you need'
Just in case you need to view the result, you can:
>>> _
'the value you need'
Although _ is also used in some Python shells as a special variable for the last value evaluated, so this might not always work. You might be able to rig up a fancy solution by assigning to a simple name that points to a property that appends to a list, but that seems like a lot of effort.
FWIW IPython can be made to not echo the value with a semicolon (e.g. 1; doesn't print anything) or can be set to not automatically echo values plus it automatically records every input and output.
I am unsure of why the variable totalspeed variable is not being passed correctly to the function startgame as the startgame function is called after the gettotalspeed function.
Exerpt from call function:
gettotalspeed(party_ids)
NoOfEvents=0
startgame(party_ids,totalspeed,distance,NoOfEvents)
Functions
def gettotalspeed(party_ids):
#Get selected party members IDS
print(party_ids)
#Obtain Speeds
ids_string = ','.join(str(id) for id in party_ids)
mycursor.execute("SELECT startspeed FROM characters WHERE CharID IN ({0})".format(ids_string))
myspeeds=mycursor.fetchall()
totalspeed=0
for speedval in myspeeds:
totalspeed=totalspeed + speedval[0]
print("totalspeed is: ",totalspeed)
return totalspeed
def startgame(party_ids,totalspeed,distance,NoOfEvents):
#Check if game end
print(totalspeed)
while distance!=0:
#Travel...
distance=distance-totalspeed
NoOfEvents=NoOfEvents+1
#Generate Random Encounter
genevent(NoOfEvents)
return NoOfEvents
Error Produced:
NameError: name 'totalspeed' is not defined
Outputs (ignoring party_ids)
totalspeed is: 15
I suspect that your problem is self-evident from the main program:
gettotalspeed(party_ids)
NoOfEvents=0
startgame(party_ids,totalspeed,distance,NoOfEvents)
Of the variables you pass to your functions, only NoOfEvents is defined. party_ids, totalspeed, and distance have no definitions.
Work through a tutorial on Python scoping rules. Most of all, note that a function defines a scoping block. Variables inside the function are reclaimed when you leave the function; their names do not apply outside of that block. Your posted program has three independent totalspeed variables.
You forgot to make totalspeed a global variable like global totalspeed in your gettotalspeed() function. You might also be confused about what return does. If you wanted to do it the "proper" way, you could do totalspeed = gettotalspeed(party_ids). Hope this helps!
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'
I'm trying to modify a function which uses a module-level variable variable defined below it, similar to this:
def say_hello():
print(MESSAGE)
MESSAGE = "Hello, world!"
say_hello()
I would like to make the message a parameter, like so:
MESSAGE = "Hello, world!"
def say_hello(message=MESSAGE):
print(message)
say_hello()
I've noticed that in order for this to work, I had to move the definition of MESSAGE up in the code. Apparently, all module-levels are first 'bound' and are then available within function bodies, but when provided as default function arguments, they have to be defined before the function. Is this correct?
(I would also like to read up on this to fully understand it; any references would be much appreciated).
... when provided as default function arguments, they have to be defined before the function. Is this correct?
Correct. Default arguments are evaluated at function definition time.
If you need them evaluated at function call time, this common pattern works:
def say_hello(message=None):
if message is None:
message = MESSAGE
print(message)
MESSAGE = "Hello, world!"
say_hello()
def say_hello():
print(MESSAGE)
# ^^^^^^^ This...
...is evaluated when say_hello is called. As long as MESSAGE has been assigned by the time say_hello is called, say_hello will see the value.
# vvvvvvv This...
def say_hello(message=MESSAGE):
print(message)
...is evaluated when say_hello is defined. Python evaluates default argument values at function definition time, so MESSAGE has to be assigned before say_hello is even defined for this to work.
While you're learning about default argument binding, give this a try:
def foo(bar=[]):
bar.append(3)
print(bar)
baz = []
faz = []
foo(baz)
foo(faz)
foo()
foo()
The calls with their own arguments will do what you expect - each one prints only one variable. But the calls to foo with the default argument may surprise you. The first time you call it, you get the expected result: [3]. The second time you call it, you may be surprised that the result is [3, 3].
There's actually nothing in this answer that isn't in the others. As others have said, the default argument is evaluated at the time the function is defined. What you see here is a consequence of that - the arguments are evaluated only at the time that the function is defined. bar=[] is evaluated once, giving you one list.
If you do object creation or function calls as part of your default argument, they only happen once, with the net result being a surprisingly static-acting argument. Most of the time, this is not what we're looking for.
The definitive reference for python is found at docs.python.org . The specific reference for defining functions is at https://docs.python.org/3/tutorial/controlflow.html#defining-functions.
I'm wanting to replace keywords with values from an associated dictionary.
file1.py
import file2
file2.replacefunction('Some text','a_unique_key', string_variable1)
file2.replacefunction('Other text','another_unique_key', string_variable2)
file2.replacefunction('More text','unique_key_3', string_variable2)
stringvariable1, used in the first function call, is a local variable in file1.py and therefore is accessible as a parameter in the function. It is intentionally a different variable than the one later used in that parameter position.
file2.py
import re
keywords = {
"a_unique_key":"<b>Some text</b>",
"another_unique_key":"<b>Other text</b>",
"unique_key_3":"<b>More text</b>",
}
def replacefunction(str_to_replace, replacement_key, dynamic_source):
string_variable2 = re.sub(str_to_replace, keywords[replacement_key], dynamic_source)
return string_variable2 <-- this variable needs to be accessible
The replacement values in the keywords dictionary are more complicated than shown above, and just demonstrated like this for brevity.
The problem occurs at the second call to replacefunction in file1.py - it cannot access stringvariable2 which is the result of the first function that is run.
I have seen that the way to access a variable produced in a function outside of that function is to do something like:
def helloworld()
a = 5
return a
mynewvariable = helloworld()
print mynewvariable
5 <-- is printed
But this approach won't work in this situation because the function needs to work on a string that is updated after each function call ie:
do this to string 2 # changes occur to string 2
do this to string 2 # changes occur to string 2
do this to string 2 # changes occur to string 2
I can achieve the required functionality without a function but was just trying to minimise code.
Is there any way to access a variable from outside a function, explicitly as a variable and not via assignment to a function?
Don't confuse variables with values. The name string_variable2 references a value, and you just return that from your function.
Where you call the function, you assign the returned value to a local variable, and use that reference to pass it into the next function call:
string_variable2 = file2.replacefunction('Some text','a_unique_key', string_variable1)
string_variable2 = file2.replacefunction('Other text','another_unique_key', string_variable2)
file2.replacefunction('More text','unique_key_3', string_variable2)
Here the replacefunction returns something, that is stored in string_variable2, and then passed to the second call. The return value of the second function call is again stored (using the same name here), and passed to the third call. And so on.