Python变量奇怪吗?

时间:2010-09-01 14:52:58

标签: python list variables reference tuples

我的Python变量发生了什么? old_pos似乎与pos

相关联

代码:

pos = [7, 7]
direction = [1, 1]
old_pos = pos
print 'pos     = '+str(pos)
print 'old_pos = '+str(old_pos)
pos[0] += direction[0]
pos[1] += direction[1]
print 'pos     = '+str(pos)
print 'old_pos = '+str(old_pos)

输出:

pos     = [7, 7]
old_pos = [7, 7]
pos     = [8, 8]
old_pos = [8, 8]

但是,如果我将old_pos = pos替换为old_pos = tuple(pos)甚至old_pos = list(pos),我就不会遇到此问题:

pos     = [7, 7]
old_pos = [7, 7]
pos     = [8, 8]
old_pos = [7, 7]

5 个答案:

答案 0 :(得分:12)

当您说old_pos = pos时,您不是要创建pos的副本,而只是创建对同一列表的另一个引用。如果您想要两个独立行为的列表,则需要制作副本,例如使用提及的list(pos)函数或使用切片表示法pos[:]

答案 1 :(得分:7)

old_pos = pos不会创建名称pos所引用的对象的副本,而是为同一个对象创建名为old_pos的第二个引用。对pos所做的操作会影响old_pos引用的同一对象。同样,名字“Steven”和“Mr. Rumbalski”都指的是我。如果你把史蒂文冲到脸上,Rumbalski先生将受伤,因为这两个名字指的是同一个物体 - 我。

以下是3种制作实际副本而非第二种引用的方法:

使用切片表示法

old_pos = pos[:]

使用列表构造函数

old_pos = list(pos)

使用复制模块

from copy import copy
old_pos = copy(pos)

请注意,这些副本都是浅色副本,在这种情况下很好。要了解浅拷贝和深拷贝之间的区别,请阅读documentation of the copy module

答案 2 :(得分:3)

  

old_pos似乎与pos

相关联

正确 - 这:

old_pos = pos

使old_pospos指向同一列表。它不会创建pos的新副本。

答案 3 :(得分:3)

递归是关于原因的。您可以看到它们具有相同的内存地址:

>>> pos = [7, 7]
>>> old_pos = pos
>>> id(pos)
4299304472
>>> id(old_pos)
4299304472

这称为通过引用传递,而不是传递值。您还可以使用copy模块来解决此问题。

>>> from copy import copy
>>> pos = [7, 7]
>>> old_pos = pos
>>> id(pos)
4299304472
>>> id(old_pos)
4299304472
>>> old_pos = copy(pos)
>>> id(old_pos)
4299349240

答案 4 :(得分:0)

除了上述注释之外,在多维数组的情况下还必须采取一些额外的步骤。例如,当您有一个二维数组var loginController = angular .module('loginController', []) .controller('LoginCtrl', LoginCtrl); LoginCtrl.$inject = [ '$rootScope', '$scope', '$location', '$timeout', 'ApiFactory', 'AUTH_EVENTS', 'AuthFactory']; function LoginCtrl( $rootScope, $scope, $location, $timeout, ApiFactory, AUTH_EVENTS, AuthFactory) { /** Init LoginCtrl scope */ /** --------------------------------------------------------------------- */ var vs = $scope; vs.login = login; $rootScope.$broadcast(AUTH_EVENTS.loginSuccess); $rootScope.$on(AUTH_EVENTS.notAuthenticated, function (event, data) { $rootScope.currentUser = null; $scope.currentUser = null; AuthFactory.logout(); $location.path('/login'); }); function login(credentials) { console.log('credentials',credentials); AuthFactory.login(credentials).then(function (user) { $rootScope.$broadcast(AUTH_EVENTS.loginSuccess); $scope.setCurrentUser(user); if (user.password_reset) { $location.path('/password'); } else { $location.path('/tickers'); } }, function () { // $scope.loginData.message = "Invalid Username/Password"; $rootScope.$broadcast(AUTH_EVENTS.loginFailed); console.log('login failed!'); } } } module.exports = loginController; 时,代码a = [[0,1,2],[3,4],[5,6,7,8]]将不会创建一个独立的副本。但是,它将创建对二维列表中相同一维列表的引用的另一个引用。要解决此问题,必须对二维列表中的每个列表使用上述方法之一。例如,b = a将创建列表的独立副本。