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
6
  • 2
    Possible duplicate of How to clone or copy a list in Python? Commented Jan 25, 2016 at 3:06
  • Ok! That answers 1. I'm still wondering 2-4 though. Commented Jan 25, 2016 at 3: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. Commented Jan 25, 2016 at 3: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? Commented Jan 25, 2016 at 3:27
  • 2
    Here's a pretty good explanation of how assignment works in Python. It should cover most of the things you asked. Commented Jan 25, 2016 at 3:39

2 Answers 2

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
Sign up to request clarification or add additional context in comments.

Comments

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

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.