Calling variables in Python (local vs global) - python

The below works and gives 8:
def mypow(a,b):
c=a**b
print (c)
mypow(2,3)
But the below doesn't:
def mypow(a,b):
c=a**b
mypow(2,3)
I understand that in the former we print but since the latter doesn't give an error message (nor does it give a result), what is actually happening in the latter?

in
def mypow(a,b):
c=a**b
mypow(2,3)
after function executed; all data inside the function destroy. if you want to see anything on your screen after function is executed; either use print or return.
In the end of any function you have multiple choices.
1- return. return the output. when you return the output you receive it after function executed without error eg: d = func(any_value), if you specified the return value in func you will receive it and store it in d. if you don't specify the return statement in the function the function will return None.
2- print. print anything. this is what you did in your first function. in this case you get printed stuff in your screen, and you function return None, so you can't hold the output (a printed value) in any variable or use it anywhere else.
3- global. assign to global. when you need this option you create a variable outside of your function say my_variale=5, and in the first line of your function you write gloabl my_variable. say the function contain 5 lines, in line #3 you did my_variable=7. after function is executed and destroyed all values within the function; when you check my_variable you will see it contains value of 5.

You can replace print with return for your function and get the same result
def mypow(a,b):
c=a**b
return c
mypow(2,3)
Variables nested in functions are treated as local variables unless you add global before the variable name.

Related

use of function , in python decorator

can someone explain how this code is working?
I mean I didn't execute the inner() function after I defined it.
So how was it executed?
I mean I did execute the hi() function, but how does it translate to the inner() function being executed?
def outer(msg):
text = msg
def inner():
print(text)
return inner
hi = outer('hi')
hi()
Your outer function returns inner. Hence hi = inner, and when you call hi() you're calling inner().
You have to realise that functions often have a return at the end. In this case your outer() function has: return inner which is the inner function defined there.
Also you must know that when you call a function which has a return, you can get hold of what is returned by assigning a variable to take that value.
Your code does this also with: hi = outer('hi'). Now your hi variable holds the reference to inner, which being a function can be called.
Your code does this also with: hi() which invokes inner() which executes and calls print(text).
The function outer is basically building a new function called inner (with a proloaded text message), and returning its handle. This construction is sometimes called "factory", because you are creating a new function with pre-loaded arguments.
The code is perfectly functional. However, it's usually considered better to define a class initialized with all the desired parameters, such as text. This helps others to understand the code better, and it looks more professional.
PS. Beware that factory functions, such as outer->inner, can easily introduce bugs. For example, consider this code:
def outer(msg):
text = msg
def inner():
print(text)
text = 'bug'
return inner
hi = outer('hi')
hi()
# prints "bug"
The meaning of text was changed after the function inner was created, but it was still affected. This is because the variable text is read from the dictionary of variables defined for the parent function (outer) at runtime. Thus, in complex applications, it can be stressing to ensure that a function such as inner is working properly.

Running function code only when NOT assigning output to variable?

I am looking for a way in python to stop certain parts of the code inside a function but only when the output of the function is assigned to a variable. If the the function is run without any assignment then it should run all the inside of it.
Something like this:
def function():
print('a')
return ('a')
function()
A=function()
The first time that I call function() it should display a on the screen, while the second time nothing should print and only store value returned into A.
I have not tried anything since I am kind of new to Python, but I was imagining it would be something like the if __name__=='__main__': way of checking if a script is being used as a module or run directly.
I don't think such a behavior could be achieved in python, because within the scope of the function call, there is no indication what your will do with the returned value.
You will have to give an argument to the function that tells it to skip/stop with a default value to ease the call.
def call_and_skip(skip_instructions=False):
if not skip_instructions:
call_stuff_or_not()
call_everytime()
call_and_skip()
# will not skip inside instruction
a_variable = call_and_skip(skip_instructions=True)
# will skip inside instructions
As already mentionned in comments, what you're asking for is not technically possible - a function has (and cannot have) any knowledge of what the calling code will do with the return value.
For a simple case like your example snippet, the obvious solution is to just remove the print call from within the function and leave it out to the caller, ie:
def fun():
return 'a'
print(fun())
Now I assume your real code is a bit more complex than this so such a simple solution would not work. If that's the case, the solution is to split the original function into many distinct one and let the caller choose which part it wants to call. If you have a complex state (local variables) that need to be shared between the different parts, you can wrap the whole thing into a class, turning the sub functions into methods and storing those variables as instance attributes.

How can I have my function called again after storing its result in a variable, each time the variable is accessed?

I have a concept where I store values returned by functions in variables which makes it easier for me.
But I am having the problem that the value in the variable isn't dynamically calling the function each time. So it returns the same value all the time.
I have made a code snip to illustrate it in a easy way:
def value():
resp = requests.get('http://www.google.com').elapsed.total_seconds()
return resp
test = value()
while True:
print test
time.sleep(10)
Output:
0.00649
0.00649
In this case, in the while true when I print test, it returns the same value, even though I am calling the function value(). How can I solve this issue? I know I can put the function in the while loop, but I want to have it as a variable.
The previous answers are correct, but please let me elaborate.
In the world of Python, things have very precise meanings but it's not always clear what is what if you are just getting started.
Expressions are things that have a value, and they include things like 123, some_variable and 10 / 2. The name some_variable is called an identifier, simply because it identifies a value. Just like the name Scruffy might identify your dog.
Statements are things that affect the program flow or the state of your program, but lack a value. The following are examples of statements:
if x > 10:
x -= 1
And
def foo(x):
print("The value of x is", x)
Unlike in JavaScript, for example, where almost everything is an expression (and has a value), you can not do this:
my_function = def foo(x): print("The value of x is", x)
The previous def statement will create a function by the name foo, but the statement itself doesn't have a value. The name foo will refer to a value, however. It means that when you write foo, the value will be a thing, and this thing is a function!
The expression x() on the other hand will do two things. First it will look up the value of the identifier x. Hopefully this value is a function. After that, the parentheses means that the value will be called. What happens if x is not a function, then?
>>> x = 10
>>> x()
Traceback (most recent call last):
File "<ipython-input-3-7354d77c61ac>", line 1, in <module>
x()
TypeError: 'int' object is not callable
Big Fat Error: 10 is not a "callable". Callable means something that can be called like a function.
The parentheses are, as you probably know, a list of arguments. In this case the list is simply empty so when you write x() you are saying "call whatever the name 'x' is referring to but don't send any arguments".
A function call always has a value, since it's an expression. If you don't explicitly return anything, the value will simply be None.
To answer your question, finally, let's play the substitution game. The rules are simple, any expression can be replaced by its value:
def value():
resp = requests.get('http://www.google.com').elapsed.total_seconds()
return resp
This is a statement, so it doesn't have a value. A function is created with the name value, however.
The function consists of two statements (no value, again), a variable assignment and a return statement.
The thing to the right of the = is an expression however. Short story:
requests is referring to the requests module
get is referring to a module-global function in the above module
get('...') is calling this function, and something is returned.
The "something" has a property called elapsed, which has a property called total_seconds.
total_seconds is an identifier that refers to a callable. The callable is called without any arguments (total_seconds()) and something is returned. Probably a number, based on the name. Let's say its value is always 10, for simplicity.
The next statement is another assignment:
test = value()
This can be thought of as "let the name 'test' refer to the value that is returned by the callable identified by the name 'value' when it is called with an empty argument list". In our case, the function object called value will be called, resp will be assigned the value 10, then the return statement will let the caller know that this call is sending the value 10 back. The name test will refer to the value 10, from now on.
Let's go over the loop, quickly:
while True:
print test
time.sleep(10)
Do the following until the end of Time:
print (a statement in Python 2, an expression in Python 3!) has the side-effect of printing stuff to the screen. Otherwise it doesn't do much.
The stuff, in this case, is whatever the value of the expression test is. We already know that the identifier test is referring to the value 10. It will simply print "10" to the screen.
Sleep for ten seconds.
Repeat.
You probably want to invoke some function at each iteration of the loop ("invoke" is basically latin for "call", I like fancy words). Otherwise the program will just print "10", "10", "10", over and over again. To fix this this, you first have to change the expression evaluated as part of the print statement from just an identifier (test) to a function call:
print test()
But this will, as we saw before, raise a Big Fat Error since 10 is not a callable function. To fix it (that's what programmers do, right?) you also need to change the value of test from 10, since it's not a callable, to the function. A function can be referred to simply by its name, so just change this line:
test = value() # equals ten
To this:
test = value # equals the function called "value"
The function now has two names, the old name "value", and the new name "test". Each step in the loop will request the page again and return the new time it took for the request to complete. If the request times out you will have a different kind of crash, but that's another story.
Further information can be found in the Python Language Reference.
test = value() isn't storing the function it's storing the results. You should just call value() in your loop or if you want to assign the function it would be test = value and then test() in your loop.
test = value() calls the function and stores the return value. It does not store the function. test = value would store the function, but the you need to print test() in order to call it.
def value():
resp = requests.get('http://www.google.com').elapsed.total_seconds()
return resp
test = value
while True:
print test()
time.sleep(10)
You can change your code like this..
def value():
resp = requests.get('http://www.google.com').elapsed.total_seconds()
return resp
test = value()
while True:
print test
time.sleep(10)
change this line
test = value
to
test = value()
Now means you are storing your function in a variable.

In python, when you pass internally defined functions into other functions, how does it keep the variables?

For example, why does this work?
def func1(func1var):
def innerfunc(innerfuncvar):
if func1var == 1:
print innerfuncvar
else:
print 5
func2(innerfunc)
def func2(function):
function(9)
When innerfunc is called in func2, how does it know the values of func1var?
You've created a closure. Basically, think of it like this, from the point of view of the inner function:
func1var = whatever
def func2(function):
function(9)
def innerfunc(innerfuncvar):
if func1var = 1:
print innerfuncvar
else:
print 5
func2(innerfunc)
It doesn't care whether func1var is in an outer or global scope -- it just looks for it in each scope outward, starting with it's own local scope. It's just like when you reference a module global variable from inside a class or function in that module.
Python actually goes to some lengths to do this for you. When you define a function inside a function, you may use variables from the outer function in the inner function. This is true for any depth of nesting (that is, you can have a function inside a function inside a function inside a function... to any depth... and the innermost function can use variables from any of the enclosing functions). If there are conflicting names, the innermost variable with the name requested is used.
What's more, Python actually captures any variables you use from the outer function and stores them in the inner function, which is called a closure. So you can not only pass a function to another function, as you are doing, but you can return a function from a function, and variables you use from the outer function that were in effect when the function was defined will still be accessible from the returned function, even though the outer function isn't running any more. This is a fairly advanced feature, but it lets you do something like this:
def make_adder(increment):
def adder(number):
return number + increment
adder.__name__ = "adder(%s)" % increment
return adder
This function is a function that creates a function that adds the specified value to it. For example:
add1 = make_adder(1)
add5 = make_adder(5)
print add1(10) # 11
print add5(10) # 15
In this case, the value you pass to make_adder is captured and stored in the function that gets returned. This allows you to create a bunch of functions that add any number to their arguments. Which is a trivial example that isn't actually very useful in real life, but serves to illustrate the feature.
Each time you call func1(func1var), Python actually builds a new function innerfunc(). Since func1var is perfectly defined when innerfunc() is created, the code of the new innerfunc() function contains the correct value of func1var.

How do I get a result (output) from a function? How can I use the result later?

Suppose I have a function like:
def foo():
x = 'hello world'
How do I get the function to return x, in such a way that I can use it as the input for another function or use the variable within the body of a program? I tried using return and then using the x variable in another function, but I get a NameError that way.
For the specific case of communicating information between methods in the same class, it is often best to store the information in self. See Passing variables between methods in Python? for details.
def foo():
x = 'hello world'
return x # return 'hello world' would do, too
foo()
print(x) # NameError - x is not defined outside the function
y = foo()
print(y) # this works
x = foo()
print(x) # this also works, and it's a completely different x than that inside
# foo()
z = bar(x) # of course, now you can use x as you want
z = bar(foo()) # but you don't have to
Effectively, there are two ways: directly and indirectly.
The direct way is to return a value from the function, as you tried, and let the calling code use that value. This is normally what you want. The natural, simple, direct, explicit way to get information back from a function is to return it. Broadly speaking, the purpose of a function is to compute a value, and return signifies "this is the value we computed; we are done here".
Directly using return
The main trick here is that return returns a value, not a variable. So return x does not enable the calling code to use x after calling the function, and does not modify any existing value that x had in the context of the call. (That's presumably why you got a NameError.)
After we use return in the function:
def example():
x = 'hello world'
return x
we need to write the calling code to use the return value:
result = example()
print(result)
The other key point here is that a call to a function is an expression, so we can use it the same way that we use, say, the result of an addition. Just as we may say result = 'hello ' + 'world', we may say result = foo(). After that, result is our own, local name for that string, and we can do whatever we want with it.
We can use the same name, x, if we want. Or we can use a different name. The calling code doesn't have to know anything about how the function is written, or what names it uses for things.1
We can use the value directly to call another function: for example, print(foo()).2 We can return the value directly: simply return 'hello world', without assigning to x. (Again: we are returning a value, not a variable.)
The function can only return once each time it is called. return terminates the function - again, we just determined the result of the calculation, so there is no reason to calculate any further. If we want to return multiple pieces of information, therefore, we will need to come up with a single object (in Python, "value" and "object" are effectively synonyms; this doesn't work out so well for some other languages.)
We can make a tuple right on the return line; or we can use a dictionary, a namedtuple (Python 2.6+), a types.simpleNamespace (Python 3.3+), a dataclass (Python 3.7+), or some other class (perhaps even one we write ourselves) to associate names with the values that are being returned; or we can accumulate values from a loop in a list; etc. etc. The possibilities are endless..
On the other hand, the function returns whether you like it or not (unless an exception is raised). If it reaches the end, it will implicitly return the special value None. You may or may not want to do it explicitly instead.
Indirect methods
Other than returning the result back to the caller directly, we can communicate it by modifying some existing object that the caller knows about. There are many ways to do that, but they're all variations on that same theme.
If you want the code to communicate information back this way, please just let it return None - don't also use the return value for something meaningful. That's how the built-in functionality works.
In order to modify that object, the called function also has to know about it, of course. That means, having a name for the object that can be looked up in a current scope. So, let's go through those in order:
Local scope: Modifying a passed-in argument
If one of our parameters is mutable, we can just mutate it, and rely on the caller to examine the change. This is usually not a great idea, because it can be hard to reason about the code. It looks like:
def called(mutable):
mutable.append('world')
def caller():
my_value = ['hello'] # a list with just that string
called(my_value)
# now it contains both strings
If the value is an instance of our own class, we could also assign to an attribute:
class Test:
def __init__(self, value):
self.value = value
def called(mutable):
mutable.value = 'world'
def caller():
test = Test('hello')
called(test)
# now test.value has changed
Assigning to an attribute does not work for built-in types, including object; and it might not work for some classes that explicitly prevent you from doing it.
Local scope: Modifying self, in a method
We already have an example of this above: setting self.value in the Test.__init__ code. This is a special case of modifying a passed-in argument; but it's part of how classes work in Python, and something we're expected to do. Normally, when we do this, the calling won't actually check for changes to self - it will just use the modified object in the next step of the logic. That's what makes it appropriate to write code this way: we're still presenting an interface, so the caller doesn't have to worry about the details.
class Example:
def __init__(self):
self._words = ['hello']
def add_word(self):
self._words.append('world')
def display(self):
print(*self.words)
x = Example()
x.add_word()
x.display()
In the example, calling add_word gave information back to the top-level code - but instead of looking for it, we just go ahead and call display.3
See also: Passing variables between methods in Python?
Enclosing scope
This is a rare special case when using nested functions. There isn't a lot to say here - it works the same way as with the global scope, just using the nonlocal keyword rather than global.4
Global scope: Modifying a global
Generally speaking, it is a bad idea to change anything in the global scope after setting it up in the first place. It makes code harder to reason about, because anything that uses that global (aside from whatever was responsible for the change) now has a "hidden" source of input.
If you still want to do it, the syntax is straightforward:
words = ['hello']
def add_global_word():
words.append('world')
add_global_word() # `words` is changed
Global scope: Assigning to a new or existing global
This is actually a special case of modifying a global. I don't mean that assignment is a kind of modification (it isn't). I mean that when you assign a global name, Python automatically updates a dict that represents the global namespace. You can get that dict with globals(), and you can modify that dict and it will actually impact what global variables exist. (I.e., the return from globals() is the dictionary itself, not a copy.)5
But please don't. That's even worse of an idea than the previous one. If you really need to get the result from your function by assigning to a global variable, use the global keyword to tell Python that the name should be looked up in the global scope:
words = ['hello']
def replace_global_words():
global words
words = ['hello', 'world']
replace_global_words() # `words` is a new list with both words
Global scope: Assigning to or modifying an attribute of the function itself
This is a rare special case, but now that you've seen the other examples, the theory should be clear. In Python, functions are mutable (i.e. you can set attributes on them); and if we define a function at top level, it's in the global namespace. So this is really just modifying a global:
def set_own_words():
set_own_words.words = ['hello', 'world']
set_own_words()
print(*set_own_words.words)
We shouldn't really use this to send information to the caller. It has all the usual problems with globals, and it's even harder to understand. But it can be useful to set a function's attributes from within the function, in order for the function to remember something in between calls. (It's similar to how methods remember things in between calls by modifying self.) The functools standard library does this, for example in the cache implementation.
Builtin scope
This doesn't work. The builtin namespace doesn't contain any mutable objects, and you can't assign new builtin names (they'll go into the global namespace instead).
Some approaches that don't work in Python
Just calculating something before the function ends
In some other programming languages, there is some kind of hidden variable that automatically picks up the result of the last calculation, every time something is calculated; and if you reach the end of a function without returning anything, it gets returned. That doesn't work in Python. If you reach the end without returning anything, your function returns None.
Assigning to the function's name
In some other programming languages, you are allowed (or expected) to assign to a variable with the same name as the function; and at the end of the function, that value is returned. That still doesn't work in Python. If you reach the end without returning anything, your function still returns None.
def broken():
broken = 1
broken()
print(broken + 1) # causes a `TypeError`
It might seem like you can at least use the value that way, if you use the global keyword:
def subtly_broken():
global subtly_broken
subtly_broken = 1
subtly_broken()
print(subtly_broken + 1) # 2
But this, of course, is just a special case of assigning to a global. And there's a big problem with it - the same name can't refer to two things at once. By doing this, the function replaced its own name. So it will fail next time:
def subtly_broken():
global subtly_broken
subtly_broken = 1
subtly_broken()
subtly_broken() # causes a `TypeError`
Assigning to a parameter
Sometimes people expect to be able to assign to one of the function's parameters, and have it affect a variable that was used for the corresponding argument. However, this does not work:
def broken(words):
words = ['hello', 'world']
data = ['hello']
broken(data) # `data` does not change
Just like how Python returns values, not variables, it also passes values, not variables. words is a local name; by definition the calling code doesn't know anything about that namespace.
One of the working methods that we saw is to modify the passed-in list. That works because if the list itself changes, then it changes - it doesn't matter what name is used for it, or what part of the code uses that name. However, assigning a new list to words does not cause the existing list to change. It just makes words start being a name for a different list.
For more information, see How do I pass a variable by reference?.
1 At least, not for getting the value back. If you want to use keyword arguments, you need to know what the keyword names are. But generally, the point of functions is that they're an abstraction; you only need to know about their interface, and you don't need to think about what they're doing internally.
2 In 2.x, print is a statement rather than a function, so this doesn't make an example of calling another function directly. However, print foo() still works with 2.x's print statement, and so does print(foo()) (in this case, the extra parentheses are just ordinary grouping parentheses). Aside from that, 2.7 (the last 2.x version) has been unsupported since the beginning of 2020 - which was nearly a 5 year extension of the normal schedule. But then, this question was originally asked in 2010.
3Again: if the purpose of a method is to update the object, don't also return a value. Some people like to return self so that you can "chain" method calls; but in Python this is considered poor style. If you want that kind of "fluent" interface, then instead of writing methods that update self, write methods that create a new, modified instance of the class.
4 Except, of course, that if we're modifying a value rather than assigning, we don't need either keyword.
5 There's also a locals() that gives you a dict of local variables. However, this cannot be used to make new local variables - the behaviour is undefined in 2.x, and in 3.x the dict is created on the fly and assigning to it has no effect. Some of Python's optimizations depend on the local variables for a function being known ahead of time.
>>> def foo():
return 'hello world'
>>> x = foo()
>>> x
'hello world'
You can use global statement and then achieve what you want without returning value from
the function. For example you can do something like below:
def foo():
global x
x = "hello world"
foo()
print x
The above code will print "hello world".
But please be warned that usage of "global" is not a good idea at all and it is better to avoid usage that is shown in my example.
Also check this related discussion on about usage of global statement in Python.

Categories