Np index_exp referencing - python

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?

Related

Set variables stored in a list to None with a for loop

I store variables in a list to access them later with a for loop.
My desire is to set some of the variables not just the list's entries to None
import numpy as np
a = np.random.rand(3,2)
b = np.random.rand(3,2)
c = np.random.rand(3,2)
data_lists = [a,b,c]
data_lists[:] = [None]
won't work. Does anyone know a pythonic way to do it without explicitly writing a = None and so on?
Perhaps you could do a = b = c = None, then recreate data_lists by doing data_lists = [a, b, c] again. You can't set a variable to None implicitly. Hope this helps

Declare multiple variable in a single line in python

I've code,
var a,b,c,d;
I need to rewrite this in python.
I'm not sure, since I'm new to python, how to define multiple variables in a sinlge line with no assignment.
I thought of doing
> a=None
> b=None
> c=None
> d=None
But it should be in one line
More pythonic way is tuple unpacking:
a, b, c, d = 1, 2, 3, 4
Or if you want to initialize to single value
a = b = c = d = 1
You could also use semi-colon (although not encouraged)
a=1; b=2; c=3; d=4
All of them would work.
You could use tuple unpacking:
a, b, c = 1, 2, 3
But to be honest, it would more Pythonic to do the assignments on separate lines.
The "to a single value" part warrants a little bit of extra explanation.
a = b = c = d = None
a = 1
print(b)
>>> None
The above statement does set the value of each variable to None, but with some other types of values, this may not always be the case. Python is an object-oriented language and if you replace the value None with another type of value that is a Python object you might get results that you don't expect (because Python sets all four variables to literally the same object). Consider:
a = b = c = d = list()
a.append(1)
print(b)
>>>[1]
The reason that the result is different is because a, b, c, and d are all referring to the same list. This is a fundamental concept in Python and a really important one to remember, and shows why making these types of one-line declarations can be potentially problematic.
As others have said, declaring your variables on the go (as you need them) is probably the better way to go overall, as it helps to avoid these types of "less obvious" declaration issues.
This will do it in a single line and several expressions
a=None; b=None; c=None; d=None
This will do it in a single line declaring all vars at once with the same value
a = b = c = d = None
And as pointed out in comments, you could even do it with 0 line since you can just use your vars on the go without prior declaration.

Did the swap happened?

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

function taking a list as argument doesn't working as expected

def example(b):
b = b + ['z']
b = [1,2,3]
example(b)
Howcome after I execute the above example, the value of b still remains
[1,2,3]
expected output
[1,2,3,'z']
This is because you are creating a new list and reassigning it to the variable b inside the function.
If you instead used .append() you would get the results you expect.
def example(b):
b.append('z')
b = [1,2,3]
example(b)
I'd suggest you look at python variable scoping for more details.

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)

Categories

Resources