0

As an illustration of my question, say I want to swap two elements in an array:

# Array Integer Integer -> Array
# I want to swap the values at locations i1 and i2. 
# I want to return the array with values swapped.
def swap(A, i1, i2):
    newA = A
    newA[i1] = A[i2]
    newA[i2] = A[i1]
    return newA

Run this code, and an array is returned with only one value changed:

> testArray = [1, 2, 3, 4]
> swap(testArray, 0, 1)
[2, 2, 3, 4]

Also, if I now check what testArray is (I want it to still be [1, 2, 3, 4]):

> testArray
[2, 2, 3, 4]

So my questions are:

  1. I guess newA = A uses a pointer to A. I'm used to programming in a style where I return a new data structure each time. I'd like to create a whole new array, newA, which just has the same values as A. Then I can let garbage collection take care of newA later. Can I do this in python?

  2. What is newA = A really doing?

  3. Why would someone create a new variable (like newA) to point to the old one (A)? Why wouldn't they just mutate A directly?

  4. And why does the syntax behave differently for atomic data?

i.e.

a = 1
b = a # this same syntax doesn't seem to be a pointer.
b = 2
> a
1
user4396936
  • 177
  • 2
  • 3
  • 11
  • 2
    Possible duplicate of [How to clone or copy a list in Python?](http://stackoverflow.com/questions/2612802/how-to-clone-or-copy-a-list-in-python) – J.J. Hakala Jan 25 '16 at 03:06
  • Ok! That answers 1. I'm still wondering 2-4 though. – user4396936 Jan 25 '16 at 03:19
  • @user4396936: Your question history shows some use of Racket. Are you familiar with how Racket's variable assignment semantics work? Because Python's assignment semantics are nearly identical. – user2357112 Jan 25 '16 at 03:21
  • I'm a novice programmer, so I haven't yet learned much about different assignment semantics. My understanding of Racket: (define a 1) a is now has the value of 1, and I will never change that. (I know racket has some ways to mutate, but I've never touched them.) (define a b) b has value of 1, also. For lists, same thing. Can you discuss how this compares to python? – user4396936 Jan 25 '16 at 03:27
  • Well, if you've never touched `set!` or similar in Racket, this comparison isn't going to be very helpful. – user2357112 Jan 25 '16 at 03:37
  • 2
    [Here's a pretty good explanation of how assignment works in Python.](http://nedbatchelder.com/text/names.html) It should cover most of the things you asked. – user2357112 Jan 25 '16 at 03:39

2 Answers2

2

If it is list of integers then you can do:

def swap(A, i1, i2):

    temp = A[i1]
    A[i1] = A[i2]
    A[i2] = temp

    return A

or more pythonic way

def swap(A, i1, i2):

    A[i1], A[i2] = A[i2], A[i1]

    return A

-

 newA = A

this create "alias" - both variables use the same list in memory. When you change value in A then you change value in newA too.

see visualization on PythonTutor.com (it is long link with Python code)

http://pythontutor.com/visualize.html#code=A+%3D+%5B1,+2,+3,+4%5D%0A%0AnewA+%3D+A&mode=display&origin=opt-frontend.js&cumulative=false&heapPrimitives=false&textReferences=false&py=2&rawInputLstJSON=%5B%5D&curInstr=2

-

To create copy you can use slicing

newA = A[:] # python 2 & 3

or

import copy

newA = copy.copy(A)
newA = copy.deepcopy(A)

or on Python 3

newA = A.copy()

-

integers and float are kept in variable but other objects are too big to keep it in variable so python keeps only reference/pointer to memory with this big object. Sometimes it is better to send reference (to function or class) than clone all data and send it.

 a = 1
 b = a # copy value

 a = [1,2,3] # big object - variable keeps reference/pointer
 b = a # copy reference
furas
  • 134,197
  • 12
  • 106
  • 148
0
  1. How to create a new list?

Some ways and timings for large and small lists:

>>> for way in 'A[:]', 'list(A)', 'A.copy()':
    print(way, timeit(way, 'A = list(range(100000))', number=10000))

A[:] 7.3193273699369
list(A) 7.248674272188737
A.copy() 7.366528860679182

>>> for way in 'A[:]', 'list(A)', 'A.copy()':
    print(way, timeit(way, 'A = list(range(10))', number=10000000))

A[:] 4.324301856050852
list(A) 7.022488782549999
A.copy() 4.61609732160332

  1. What is newA = A really doing?

Makes variable newA reference the same object A references.


  1. Why would someone create a new variable (like newA) to point to the old one (A)? Why wouldn't they just mutate A directly?

Just an example:

if <something>:
    now = A
    ...
else:
    now = B
    ...
<modify now>

  1. And why does the syntax behave differently for atomic data?

It doesn't. It does make the new variable reference the same object, also for ints. You just don't notice it, because ints can't be changed. But you can see it by testing with is:

>>> a = 1234
>>> b = a
>>> b is a
True               <== See?
>>> b = 1234
>>> b is a
False              <== And now it's a different 1234 object
Stefan Pochmann
  • 27,593
  • 8
  • 44
  • 107