Remember Array value after Function call - python

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)

Related

How to create a global variable in python

In my program I need a counter, but it just counts to one and not higher. Here is my code:
# set a counter variable
c = 0
def counter(c):
c += 1
print(c)
if c == 10:
methodXY()
def do_something():
# here is some other code...
counter(c)
this is the important part of my code. I guess the problem is that the method counter() starts with the value 0 all the time, but how can I fix that? Is it possible that my program "remembers" my value for c? Hope you understand my problem. Btw: I am a totally beginner in programming, but I want to get better
If you want to use outer variable "c" inside your function, write it as global c.
def counter():
global c
c += 1
print(c)
if c == 10:
methodXY()
You always call the function with the value 0 (like you expected). You can return "c"
and call it again.
Look:
# set a counter variable
c = 0
def counter(c):
c += 1
print(c)
return c
def do_something(c):
c=counter(c)
return c
for i in range(10):
c=do_something(c)

Python alternative to global variables

In this example test_function1 has 4 varibles that need to be used in test_funtion2.I would not like using global variables becouse the actual code i'm writing is more complex and it would break it.
def test_function1():
a = input("Type aaa:")
b = "bbb"
c = "ccc"
d = "ddd"
test_funtion1()
def test_function2():
if a == "aaa"
print(b)
print(c)
print(d)
test_function2()
I have a solution, but I am not sure if it is good or not.Could you tell me if this would work or if there is any other alternative.Thanks!
Sorry for my grammar , english is not my main language.
def test_function1():
a = input("Type aaa:")
b = "bbb"
c = "ccc"
d = "ddd"
return (a, b, c, d)
def test_function2():
if (test_funtion1()[0]) == "aaa"
print(test_funtion1()[1])
print(test_funtion1()[2])
print(test_funtion1()[3])
I think what you're looking for are classes.
a, b,c, d is your state, and an instantiation of such a class forms a state, which is basically the values referenced by these 4. Your first function is the "constructor" (called __init__) and the second function is then able to access these "instance variables".
I edited the solution that best fits me:
def test_function1():
a = input("Type aaa:")
b = "bbb"
c = "ccc"
d = "ddd"
return a, b, c, d
def test_function2():
x = test_function1()
if x[0] == "aaa":
print(x[1])
print(x[2])
print(x[3])
test_funtion2()
Passing arguments to functions and returning values from functions is indeed the first and most obvious way to avoid global state - but wrt/ to your snippet, you should avoid calling test_function1 four times, which is done by keeping the result in a local variable:
def test_function2():
result = test_funtion1()
if result[0] == "aaa"
print(result[1])
print(result[2])
print(result[3])
or in this specific case (when the function returns a tuple or ny sequence of known length) you could use tuple unpacking:
def test_function2():
a, b, c, d = test_funtion1()
if a == "aaa"
print(b)
print(c)
print(d)
Also, if you have a set of functions working on the same set of (related) variables, you may want to have a look at classes and objects.
You can also use this
def test_function1():
a = input("Type aaa:")
b = "bbb"
c = "ccc"
d = "ddd"
t = a, b, c, d
return t
def test_function2():
x = test_function1()
if x[0] == "aaa":
print(x[1])
print(x[2])
print(x[3])
test_function2()

Changing a local variable in a function from another function

First, here's my example code:
EDIT: I should have specified, in my real code, that_func() is already returning another value, so I want it to return one value, and change c in addition
EDIT 2: Code edited to show what I mean
def this_func():
c=1 # I want to change this c
d=that_func()
print(c, d)
def that_func():
this_func.c=2 #Into this c, from this function
return(1000) #that_func should also return a value
this_func()
What I want to do is change the local variable c in this_func() to the value I assign it in that_func(), so that it prints 2 instead of 1.
From what I've gathered online, this_func.c=2 should do just that, but it doesn't work. Am I doing something wrong, or have I misunderstood?
Thanks for any and all help.
Yes, you misunderstood.
functions are not class. You can't access variables of a function like that.
Obviously, it's not the smartest of code that can be written, but this code should give an idea about how to use variables of a function.
def this_func():
c=1 # I want to change this c
c=that_func(c) # pass c as parameter and receive return value in c later
print(c)
def that_func(b): # receiving value of c from this_func()
b=2 # manipulating the value
return b #returning back to this_func()
this_func()
Wrap it in an object and pass it to that_func:
def this_func():
vars = {'c': 1}
d = that_func(vars)
print vars['c'], d
def that_func(vars):
vars['c'] = 2
return 1000
Alternatively, you can pass it in as a regular variable and that_func can return multiple values:
def this_func():
c = 1
c, d = that_func(c)
print c, d
def that_func(c):
c = 2
return c, 1000

Make function change variables in main code

I want to make a function that does the following:
def func(*args):
for arg in args:
arg+=1
a = 5
b = 6
c = 7
func(a,b,c)
print("%i,%i,%i"%(a,b,c))
I want it to return:
6,7,8
How would I do this?
You can’t! Ta-da.
Python does not support pass-by-reference in any form. Return values instead:
def func(*args):
return [arg + 1 for arg in args]
a = 5
b = 6
c = 7
a, b, c = func(a, b, c)
print("%i,%i,%i" % (a, b, c))
You can't do this, because when you pass in a variable, it takes it in as its value, not as its variable.
Instead, return the value:
def func(*args):
args = list(args)
for i in range(len(args)):
args[i]+=1
return args
a = 5
b = 6
c = 7
a, b, c = func(a,b,c)
print("%i,%i,%i"%(a,b,c))
Which outputs:
>>> print("%i,%i,%i"%(a,b,c))
6,7,8
>>>
You can't, at least not with integer values. Integers are immutable, so you can't change their values, and a function doesn't have access to the namespace of its caller, so you can't rebind the variables (i.e., assign a new value to the variable a outside the function). See this question and various others about what you can and cannot do to affect variables in functions.
If your variables are mutable types like lists, you can achieve a similar effect by mutating the list's value:
def func(*args):
for arg in args:
arg[0] += 1
a = [5]
b = [6]
c = [7]
func(a,b,c)
print("%i,%i,%i"%(a,b,c))
However, you should think about why you want to do this. It may be better to simply return the values and assign them outside the function.
3 posts to tell "You can't" But "Impossible n'est pas français".
Python is the lingua franca of programming languages.
So it's possible:
#!/usr/bin/env python
def func(args):
for i in range(len(args)):
args[i] += 1
abc = [5, 6, 7]
func(abc)
print("%i,%i,%i" % tuple(abc))
actually prints
6,7,8
You can't do it easily because Python doesn't pass immutable objects such as integers by reference. However if you pass the function the names of objects in the current scope, you can achieve your goal like this:
import sys
def func(*args):
namespace = sys._getframe(1).f_globals # caller's globals
for arg in args:
namespace[arg] += 1
a = 5
b = 6
c = 7
func('a','b','c') # note variable *names* passed to function
print("%i,%i,%i" % (a,b,c)) # -> 6,7,8

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)

Categories

Resources