1

我看了一下python代码,其中字符串变量分配看起来像:

var1 = var2[:]

我只是想知道有什么区别:

var1 = var2

这是我的实验:

>>> original = "some text"
>>> copy1 = original
>>> copy2 = original[:]
>>> original = "another text"
>>> copy1
'some text'
>>> copy2
'some text'

更新:

这是一个完整的代码。此代码搜索替换密码的密钥。如果我删除 '[:]' 此代码将运行非常缓慢。

4

5 回答 5

5

由于interning,两者之间通常没有区别(在结果对象中)。我们可以通过操作符检查两个变量是否指向同一个对象,与is操作==符检查对象的实际内存地址是否相同:

>>> a = "foo"
>>> b = a
>>> a is b
True
>>> c = a[:]
>>> a is c
True

实习是一种节省内存和加速不可变对象比较的机制,它的工作原理是这样的:在创建新的不可变对象之前,python 检查是否已经存在相同的不可变对象。如果是这样,它只使用对现有对象的引用。它可以做到这一点而不会造成伤害,因为没有办法改变不可变的。这就是为什么即使是两个独立创建的字符串也可能指向同一个对象:

>>> a = "foo"
>>> b = "foo"
>>> a is b
True

但是,如果var2是一些可变的顺序对象,例如 a list,那么var2[:]将是 的浅拷贝var2,因此对一个对象进行更改不会影响另一个对象。

>>> a = list("foo")
>>> a
['f', 'o', 'o']
>>> b = a
>>> b is a
True
>>> c = a[:]
>>> c is a
False
>>> b.pop()
'o'
>>> a
['f', 'o']
>>> b
['f', 'o']
>>> c
['f', 'o', 'o']

如需了解全貌,另请阅读 Ashwini Chaudharys 的回答。

于 2012-11-06T08:20:30.850 回答
2

[:] 表示法用于切片,

a[m:n]将返回从 index mupto开始的字符n-1,如果没有传递任何内容,则返回整个字符串。

In [1]: a="foobar"

In [2]: a[:]          #this is equal to a only as nothing to passed to slicing
Out[2]: 'foobar'

In [3]: a[1:]         #return everything after index 1
Out[3]: 'oobar'

In [4]: a[:1]         #return everything before 1st index
Out[4]: 'f'

In [5]: a[:-1]        #return everything before the last character
Out[5]: 'fooba'

b=a[:]和之间的区别在于b=ab=a 在内部采用更少的步骤:

In [7]: def func1():
   ...:     a="foo"
   ...:     b=a
   ...:     

In [8]: def func2():
   ...:     a="foo"
   ...:     b=a[:]
   ...:     

In [9]: dis.dis(func1)
  2           0 LOAD_CONST               1 ('foo')
              3 STORE_FAST               0 (a)

  3           6 LOAD_FAST                0 (a)
              9 STORE_FAST               1 (b)
             12 LOAD_CONST               0 (None)
             15 RETURN_VALUE        

In [10]: dis.dis(func2)
  2           0 LOAD_CONST               1 ('foo')
              3 STORE_FAST               0 (a)

  3           6 LOAD_FAST                0 (a)
              9 SLICE+0             
             10 STORE_FAST               1 (b)
             13 LOAD_CONST               0 (None)
             16 RETURN_VALUE 

timeit

In [11]: %timeit func1()
1000000 loops, best of 3: 336 ns per loop

In [12]: %timeit func2()
1000000 loops, best of 3: 397 ns per loop
于 2012-11-06T08:21:53.410 回答
1

在您链接到的完整代码中,有可能original是 a list,而不是 a str

parentkey,parentscore = startkey or list('ABCDEFGHIJKLMNOPQRSTUVWXYZ'),-99e99

进而

child = parentkey[:]
# swap two characters in the child
child[a],child[b] = child[b],child[a]

正如lazer所提到的,在这种情况下,创建一个副本会有所作为。

于 2012-11-06T08:24:47.370 回答
1

请注意,在您的代码中,变量可以是 alist而不是字符串。

请参见以下示例:

>>> a = [1,2,3]
>>> b = a
>>> b[0] = 'foo'
>>> a
['foo', 2, 3]

但:

>>> a = [1,2,3]
>>> b = a[:]
>>> b[0] = 'foo'
>>> a
[1, 2, 3]

换句话说,在第一个示例中,对的引用a被保留在b并更改b更改a中。使用切片表示法[:]可以进行深度(1 级)复制。

于 2012-11-06T08:26:00.477 回答
0

a[:]和 just 一样aid(a) == id(a[:])所以没有区别)

a = 'Convert an integer number to a binary string Convert an integer number to a binary'
id(a) == id(a[:])
>>> True

对于 list [:] 返回它的副本。

a = [1, 2, 3]
id(a) == id(a[:])
>>> False
于 2012-11-06T08:24:39.847 回答