Why some variables have changed and some have not? [duplicate] - python

This question already has answers here:
How do I pass a variable by reference?
(39 answers)
Closed 3 months ago.
Why the variables a, c, d have not changed, but b has changed?
a = 0
b = []
c = []
d = 'a'
def func_a(a):
a += 1
def func_b(b):
b += [1]
def func_c(c):
c = [2]
def func_d(d):
d += 'd'
func_a(a)
func_b(b)
func_c(c)
func_d(d)
print('a = ', a)
print('b = ', b)
print('c = ', c)
print('d = ', d)
I think it has to do with the fact that all variables are global, but I don't understand why b changes then..

This is related by local and global scope, you can update using change the name of function parameter names;
a = 0
def func_a(local_a):
global a
a += 1
func_a(a)
print('a = ', a)
# output: a = 1
"global a" meaning this function will use the global scope of a.
If you try to use with this way;
a = 0
b = []
c = []
d = 'a'
def func_a(a):
global a
a += 1
func_a(a)
print('a = ', a)
You will get an error like this;
File "glob_and_local.py", line 8
global a
^^^^^^^^
SyntaxError: name 'a' is parameter and global
Because same names are conflicting.

Here, a, b, c, d are global variables.
For a:
a is an integer. when you are calling func_a(a) you are only making changes in the local scope but not returning anything. That's why there is no change in the global variable a.
Same thing happening with global variables c and d.
For b:
You are passing an array and appending an array into it.
append method makes changes in global variables too.
NOTE:
here, b += [1] is equivalent to b.append(1)

Related

Problem with local variable. NameError: name 'b' is not defined in python

There is something wrong with my code. I still don't understand how local variable works. The following is an example of a simple code. And I have a NameError issue. Why? How can I fix this? I need to fix this error without Global variables! And there must be variable(a) ! What should I do for the answer of this code to come out 21?
def first(a):
a = 0
b = 3
return b
def second(a):
a = 0
j = 7
return j
def result():
return first(b) * second(j) # <-NameError: name 'b' is not defined in python
print(result())
You should define what does your b and j mean in string 10:
For python you are giving noting to function, but this function is asking for some value (a), it should be like this:
def first(a):
a = 0
b = 3
return b
def second(a):
a = 0
j = 7
return j
def result():
b = 123 # Defining what are we giving to our functions
j = 5
return first(b) * second(j) # Now it will work
print(result())
So you can use b and j value, and access return values:
b = 3
return b
j = 7
return j
Think like this, when you're returning some value, it fully replaces function with that value.
Here, b is only defined within the scope of function first()
This means that any code outside of this function cannot access that variable.
Unless the variable is marked as global b it will only be accessible within that 'block' of code
Example:
# Variable not defined in a function, therefore in global scope.
a = 10
def foo():
# Variable defined in function, only accessible within function
b = 10
# NOT RECCOMENDED
# Variable marked as global and accessible anywhere after assignment
global c
c = 10
# Additional Note (Not important or useful)
# Non local overrides local variables with a variable in an outer but not global scope
d = 10
def bar():
nonlocal d
d = 20
print(a) # 10 - No error, in global scope
print(b) # Error - b not in global scope
print(c) # 10 - No error, in global scope
# nonlocal (ignore)
print(d) # Error - d not in global scope
Short answer: local variables can only be used inside the function where they are defined.
Let's look at your code to see what is going on:
def first(a):
a = 0
b = 3. # b is defined inside of `first()`
return b
def second(a):
a = 0
j = 7
return j
def result():
return first(b) * second(j) # trying to use `b` inside result() gives an error because there is no variable with that name defined here.
print(result())
See the comments on the relevant lines. I don't know what you are trying to do here, so I can't give any suggestions about how to fix it.

Call a variable outside of a function? [duplicate]

This question already has answers here:
Using global variables in a function
(25 answers)
Closed 3 years ago.
For example:
def test(a)
a = 2
b = 5+a
x = a*2
return x
Is there a way to call the variable 'b' outside of the function?
b = None
def test(a)
global b
a = 2
b = 5+a
x = a*2
return x
print(b)
Although we will suggest to return b and then access it, as global variable is a bad idea.
See this,
Why are global variables evil?

Remember Array value after Function call

If I write this:
c = []
def cf(n):
c = range (5)
print c
if any((i>3) for i in c) is True:
print 'hello'
cf(1)
print c
Then I get:
[1, 2, 3, 4]
hello
[]
I'm really new to programming, so please explain it really simply, but how do I stop Python from forgetting what c is after the function has ended? I thought I could fix it by defining c before the function, but obviously that c is different to the one created just for the function loop.
In my example, I could obviously just write:
c = range (5)
def cf(n)
But the program I'm trying to write is more like this:
b = [blah]
c = []
def cf(n):
c = [transformation of b]
if (blah) is True:
'loop' cf
else:
cf(1)
g = [transformation of c that produces errors if c is empty or if c = b]
So I can't define c outside the function.
In python you can read global variables in functions, but you cant assigned to them by default. the reason is that whenever python finds c = it will create a local variable. Thus to assign to global one, you need explicitly specify that you are assigning to global variable.
So this will work, e.g.:
c = [1,2,3]
def cf():
print(c) # it prints [1,2,3], it reads global c
However, this does not as you would expect:
c = [1,2,3]
def cf():
c = 1 # c is local here.
print(c) # it prints 1
cf()
print(c) # it prints [1,2,3], as its value not changed inside cf()
So to make c be same, you need:
c = [1,2,3]
def cf():
global c
c = 1 # c is global here. it overwrites [1,2,3]
print(c) # prints 1
cf()
print(c) # prints 1. c value was changed inside cf()
To summarise a few of these answers, you have 3 basic options:
Declare the variable as global at the top of your function
Return the local instance of the variable at the end of your function
Pass the variable as an argument to your function
You can also pass the array c into the function after declaring it. As the array is a function argument the c passed in will be modified as long as we don't use an = statement. This can be achieved like this:
def cf(n, c):
c.extend(range(5))
print c
if any((i>3) for i in c) is True:
print 'hello'
if __name__ == '__main__':
c = []
cf(1, c)
print c
For an explanation of this see this
This is preferable to introducing global variables into your code (which is generally considered bad practice). ref
Try this
c = []
def cf(n):
global c
c = range (5)
print c
if any((i>3) for i in c) is True:
print 'hello'
cf(1)
print c
If you want your function to modify c then make it explicit, i.e. your function should return the new value of c. This way you avoid unwanted side effects:
def cf(n, b):
"""Given b loops n times ...
Returns
------
c: The modified value
"""
c = [transformation of b]
...
return c # <<<<------- This
c = cf(1)

Python: variables not cumulative passing through functions

I am writing a function for a text adventure I'm making that acts as a progress bar when the player receives experience (which then levels the player up upon reaching 100). For some reason altering the values of my variables inside the function does not change their values outside the function even though I've returned all three. This becomes apparent when I try calling the function twice, each time adding 85 to the variable a.
Within the function, the objective is to pass the value of a to b, check if b is greater than or equal to 100, if so add 1 to c and remove 100 from b, then reset a to 0, print the result, and return the new values.
a = new experience b = current experience c = player level
a = 0
b = 0
c = 1
def func_1(a, b, c):
b = b + a
loop1 = 0
while loop1 < 1:
if b >= 100:
print(" ")
print("Add 1!")
print(" ")
c = c + 1
b = b - 100
else:
loop1 = loop1 + 1
a = a - a
print("c is " + str(c))
print("b is " + str(b))
print("a is " + str(a))
return a
return b
return c
a = a + 85
func_1(a, b, c)
a = a + 85
func_1(a, b, c)
print a, b, c
I'm really new to programming so I apologize for any inefficiencies. Thank you for any help and let me know if something doesn't make sense/is unclear.
Couple of things I see here:
First, out of the three return statements at the end of your code, only the first, return a, is executed. A return statement immediately stops execution of the function; return b and return c are never touched.
Second, you're having some confusion with the scope of the variables. a, b, and c defined outside of the function are global variables, while the a, b, and c passed into the function are local to the scope of the function. Thus, any modifications to the variables in your function won't affect the global variables.
You can do two things. First, have a global declaration at the beginning of the function:
def func_1():
global a
global b
global c
# Function body
This indicates to the function that a, b, and c are global variables that exist outside the function. Thus, passing in arguments is no longer needed; the function will search for variables outside the function. However, this is bad programming practice. The better option is to have func_1 return the modified values and reassign the global values to these new values, like so:
def func_1(a, b, c):
# Function body
return (a, b, c)
Then, to call the function and modify the variables outside the function:
a, b, c = func_1(a, b, c)
A couple suggestions:
You have a lot of incrementing going on, and python has specialized syntax for it: b = b + a can be shortened to b += a, c = c + 1 to c += 1, b = b - 100 to b -= 100. Also, simply reset a to 0 with a = 0 instead of subtracting a - a. Also, you don't need print(" "); print() will suffice.
Next, your while loop is unnecessary. Your function only needs to check once whether b >= 100, so there's no need to set up a loop. Increment b and then use a simple if statement to level up if necessary:
def func_1(a, b, c):
b += a
if b >= 100:
print("\nAdd 1!\n")
c += 1
b -= 100
a = 0
# Rest of the function
Inside func_1() the names a,b,c are local. When you change them nothing happens to the external a,b,c. You return the values correctly in the function, but then when calling the function you need to assign the values to the variables like this: a,b,c=func_1(a,b,c).
Returning a value doesn't set it unless you explicitly assign it in the calling function:
a, b, c = func_1(a, b, c)
Assigning inside the function doesn't affect the outer ones because they are considered "local scope". To counter that declare them global to affect the outer variables:
def func_1():
global a
global b
global c
Only one of these should be implemented
It is generally preferred not to declare globals. Ideally you should make a class for all of this, but these two options would require the least refactoring of your existing code
Note that a global variable (the variables outside of the function) are completely separate from the local variables (the variables inside the function).
This doesn't work because you can only return once. When you returned a, the function immediately stopped.
Also, since you didn't set any variable to the returned value, the global variables outside of the loop were unaffected. What you can do is return the a, b, and c values as a tuple, and then set the a, b and c global variables to that tuple.
return (a, b, c)
a, b, c = func_1(a, b, c)

I keep on getting NameError: name 'a' is not defined?

def main():
a == 3
b = a + 1
c = b + 1
print(a)
if (a<0):
print(a<0)
print(c)
else:
print('a is not less than 0')
print(a)
I watched the khan academy video #1 on Python programming and tried to duplicate it but it kept on giving the error above.
Thanks for your help
I am a first time python user
You are not assigning to a; you are instead testing for equality with a double ==:
a == 3
Since you didn't assign anything to a yet to compare with 3, that results in a NameError.
Remove one = sign to assign instead:
a = 3
This all assumes that the rest of your code is indented correctly to match the rest of your function:
def main():
a = 3
b = a + 1
c = b + 1
print(a)
if (a<0):
print(a<0)
print(c)
else:
print('a is not less than 0')
print(a)
== is used for comparison tests. You need to use = for variable assignment:
a = 3
Also, as your code currently stands, the stuff outside of main will not be able to access a because it is local to the function. Hence, you need to indent it one level:
def main():
a = 3
b = a + 1
c = b + 1
print(a)
if (a<0):
print(a<0)
print(c)
else:
print('a is not less than 0')
print(a)
main()
I think you want the following code:
def main():
a = 3
b = a + 1
c = b + 1
print(a)
if (a<0):
print(a<0)
print(c)
else:
print('a is not less than 0')
print(a)
main()
You want the if statements to be inside the function that you're making, in this case main(). Otherwise, 'a' will not be defined because it is inside the function main(). Welcome to python, and to stack overflow!

Categories

Resources