如何在内存中创建一个新的数据对象,而不是指向一个? (在Python 3中)

时间:2016-01-25 03:02:16

标签: python arrays pointers

作为我的问题的一个例子,我想要在数组中交换两个元素:

# 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

运行此代码,返回一个只更改了一个值的数组:

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

另外,如果我现在检查testArray是什么(我希望它仍然是[1,2,3,4]):

> testArray
[2, 2, 3, 4]

所以我的问题是:

  1. 我猜newA = A使用指向A的指针。我习惯于每次返回新数据结构的样式进行编程。我想创建一个全新的数组newA,它与A具有相同的值。然后我可以让垃圾收集在以后处理newA。我可以在python中执行此操作吗?

  2. 什么是newA = A真的在做什么?

  3. 为什么有人会创建一个新变量(如newA)来指向旧变量(A)?他们为什么不直接改变A?

  4. 为什么原子数据的语法行为不同?

  5. a = 1
    b = a # this same syntax doesn't seem to be a pointer.
    b = 2
    > a
    1
    

2 个答案:

答案 0 :(得分:2)

如果是整数列表,那么你可以这样做:

def swap(A, i1, i2):

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

    return A

或更多pythonic方式

def swap(A, i1, i2):

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

    return A

-

 newA = A

这创建“别名” - 两个变量在内存中使用相同的列表。当您更改A中的值时,您也会更改newA中的值。

在PythonTutor.com上查看可视化(它是与Python代码的长链接)

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

-

要创建副本,您可以使用slicing

newA = A[:] # python 2 & 3

import copy

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

或在Python 3上

newA = A.copy()

-

integersfloat保存在变量中,但是其他对象太大而无法将其保存在变量中,因此python仅使用此大对象保留对内存的引用/指针。有时最好发送引用(到函数或类)而不是克隆所有数据并发送它。

 a = 1
 b = a # copy value

 a = [1,2,3] # big object - variable keeps reference/pointer
 b = a # copy reference

答案 1 :(得分:0)

  
      
  1. 如何创建新列表?
  2.   

大小列表的一些方式和时间:

>>> 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. 什么是newA = A真的在做什么?
  2.   

使变量newA引用相同的对象A引用。

  
      
  1. 为什么有人会创建一个新变量(如newA)来指向旧变量(A)?他们为什么不直接改变A?
  2.   

只是一个例子:

if <something>:
    now = A
    ...
else:
    now = B
    ...
<modify now>
  
      
  1. 为什么原子数据的语法行为不同?
  2.   

它没有。它确实使新变量引用相同的对象,也用于int。你只是没有注意到它,因为不能改变整数。但是你可以通过is测试来看到它:

>>> a = 1234
>>> b = a
>>> b is a
True               <== See?
>>> b = 1234
>>> b is a
False              <== And now it's a different 1234 object