Is it worth deleting variables from my Python code and using gc.collect() before the code ends? Won't the data be automatically deleted when the code finishes?
Simple example:
import gc
a = 1
b = 2
c = a + b
del a, b, c
gc.collect()
# end of code
Related
I got this code here:
a = np.zeros([32,32])
b = np.index_exp[:3,:3]
c = a[b]
c=1
a will still be a bunch of zeros. It won't change because of what happens to c.
But if I do this
a = np.zeros([32,32])
b = np.index_exp[:3,:3]
c = a[b]
c[:]=1
Now a changes. Why? It looks like in the first example I completely reassigned c, but in the second I assigned all of the values of c and then there was a reference? Anyone know the specifics?
I found this code in CodeChef twitter https://twitter.com/codechef/status/941329495046459395 . It was written in C. I did it in Python3. Here is my code:
def vegas(a,b):
temp = a
a = b
b = temp
a = 6
b = 9
print(a,b)
vegas(a,b)
print(a,b)
And this is the answer:
6 9
6 9
My question is, why my 'vegas' function is not swapping the value of variable 'a' and 'b'
It won't work the way you intend it for work. This question is answering this in full. In short: Python turns the arguments a and b into two variables which are only visible in vegas. They are initiated with the values of a and b but then have no relation to the outside a and b variables.
To make your code work, do this:
def vegas(a,b):
temp = a
a = b
b = temp
return a,b
a = 6
b = 9
print(a,b)
a,b = vegas(a,b)
print(a,b)
Also, you might be interested to know that you can swap two values with a,b = b,a
This code snippet is a joke that "what happens in vegas stays in vegas" because the function doesn't affect the values of the variables. To affects the values, the function needs to return the result of the swap. Without a return statement, the function will not affect variables since the function creates its own temporary variables to be used within the function.
Yes and no...
The function vegas do the work but never returns a and b so a and b still 6 and 9 outside. Arguments are passed by assignment in Python.
You can see more here
In python, why do loop variables overwrite already defined global variables? It seems counterintuitive that a loop variable is put into the module's global namespace rather than a new local namespace just for the loop. Here's an example that shows what I'm talking about:
c = 3.14
print("before loop c = {}".format(c))
for c in range(3):
print("in loop c = {}".format(c))
print("after loop c = {}".format(c))
Running this code will print out:
before loop c = 3.14
in loop c = 0
in loop c = 1
in loop c = 2
after loop c = 2
Reusing names like this is almost definitely bad coding style, but it may happen accidentally in large modules and cause globals to be defined where you don't expect them to be. For example if I were to do this:
def f(x):
print("x is {}".format(c)) # finger slipped, wrote c instead of x
for c in range(3):
print("c is {}".format(c))
for a in "test":
f(a)
I would get:
c is 0
c is 1
c is 2
x is 2
x is 2
x is 2
x is 2
This question seems to indicate that for loops don't have their own namespace by design. What is the rationale behind this when it can cause bugs depending on when loops are run relative to the execution order of the program?
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)
I wrote a test program that looked like this:
#!/usr/bin/python
def incrementc():
c = c + 1
def main():
c = 5
incrementc()
main()
print c
I'd think that since I called incrementc within the body of main, all variables from main would pass to incrementc. But when I run this program I get
Traceback (most recent call last):
File "test.py", line 10, in <module>
main()
File "test.py", line 8, in main
incrementc()
File "test.py", line 4, in incrementc
c = c + 1
UnboundLocalError: local variable 'c' referenced before assignment
Why isn't c passing through? And if I want a variable to be referenced by multiple functions, do I have to declare it globally? I read somewhere that global variables are bad.
Thanks!
You're thinking of dynamic scoping. The problem with dynamic scoping is that the behavior of incrementc would depend on previous function calls, which makes it very difficult to reason about the code. Instead most programming languages (also Python) use static scoping: c is visible only within main.
To accomplish what you want, you'd either use a global variable, or, better, pass c as a parameter. Now, because the primitives in Python are immutable, passing an integer can't be changed (it's effectively passed by value), so you'd have to pack it into a container, like a list. Like this:
def increment(l):
l[0] = l[0] + 1
def main():
c = [5]
increment(c)
print c[0]
main()
Or, even simpler:
def increment(l):
return l + 1
def main():
c = 5
print increment(c)
main()
Generally, global variables are bad because they make it very easy to write code that's hard to understand. If you only have these two functions, you can go ahead and make c global because it's still obvious what the code does. If you have more code, it's better to pass the variables as a parameter instead; this way you can more easily see who depends on the global variable.
When a variable is assigned to in a scope, Python assumes it's local for the whole scope unless you tell it otherwise.
So, to get this to work as you think it will, you need to use two global statements:
#!/usr/bin/python
def incrementc():
global c
c = c + 1
def main():
global c
c = 5
incrementc()
main()
print c
Otherwise, you're talking about a local variable named c in both situations.
The normal way to solve this, however, does not involve globals.
#!/usr/bin/python
def incrementc(c):
c = c + 1
return c
def main():
c = 5
c = incrementc(c)
return c
c = main()
print c
Here, in each function and in the global scope, c refers to a different variable, which you are passing around as an argument and with return values. If you wanted only one c, use a class:
class Foo:
def __init__(self, c):
self.c = c
self.incrementc()
def incrementc(self):
self.c = self.c + 1
foo = Foo(5)
print foo.c
The variable c isn't passing through because you do not hand any reference to c to the function incrementc.
What you're looking at here are 3 scopes, the global scope and those within the functions main and incrementc. In main you've properly defined a variable c, but increment c has no knowledge of this - so attempting to increment it is going to fail. Even if those two functions succeeded, trying to print c would fail in the global scope because it has no knowledge of the c you've defined in main.
You have a few options. One way to do this:
def incrementc(c):
c = c + 1
return c
def main():
c = 5
c = incrementc(c)
return c
c = main()
print c
Notice how c is being handed around. Of course, the name doesn't have to be preserved, you very well could write it like this:
def increment(z):
z = z + 1
return z
def main():
bar = 5
bar = increment(bar)
return bar
foo = main()
print foo
Another option that many would probably dislike (for good reason) is to use globals. In that case:
def incrementc():
global c # indicate intention to write to this global, not just read it
c = c + 1
def main():
global c # declares c in global space
c = 5
incrementc()
main()
print c
Any function in which you hope to MODIFY the GLOBAL instance of c, you need to inform the function. So you state, 'global c'. You can READ from the global without doing so. This would ensure (to some extent) that you don't make a mistake and overwrite a value in the global space unintentionally with a similar name, should you decide to use one in the local space of a function.
Hopefully that's clear enough, but feel free to ask for clarification on any point (I'm also open to being corrected if I've mistakenly described any part of this).
Global variables are bad.
Just like friends and enemys. Keep your friends close but keep your enemys even closer.
The function main last a local variable c, assignment the value 5
You then call the function inc..C. The c from main is now out of scope so you are trying to use a value of c that is not in scope - hence the error.