25

我只是在学习 python,我正在学习https://developers.google.com/edu/python/strings上的教程

字符串切片部分下

s[:] is 'Hello' -- 省略两者总是给我们一个完整的副本(这是复制字符串或列表等序列的pythonic方式)

出于好奇,您为什么不直接使用=运算符?

s = 'hello';
bar = s[:] 
foo = s 

据我所知,两者bar具有foo相同的价值。

4

4 回答 4

41

=做一个参考,通过使用[:]你创建一个副本。对于不可变的字符串,这并不重要,但对于列表等来说,它是至关重要的。

>>> s = 'hello'
>>> t1 = s
>>> t2 = s[:]
>>> print s, t1, t2
hello hello hello
>>> s = 'good bye'
>>> print s, t1, t2
good bye hello hello

但:

>>> li1 = [1,2]
>>> li = [1,2]
>>> li1 = li
>>> li2 = li[:]
>>> print li, li1, li2
[1, 2] [1, 2] [1, 2]
>>> li[0] = 0
>>> print li, li1, li2
[0, 2] [0, 2] [1, 2]

那么为什么在处理字符串时使用它呢?内置字符串是不可变的,但是每当您编写需要字符串的库函数时,用户可能会给您一些“看起来像字符串”和“行为像字符串”的东西,但它是一种自定义类型。这种类型可能是可变的,所以最好注意这一点。

这种类型可能看起来像:

class MutableString(object):
    def __init__(self, s):
        self._characters = [c for c in s]

    def __str__(self):
        return "".join(self._characters)

    def __repr__(self):
        return "MutableString(\"%s\")" % str(self)

    def __getattr__(self, name):
        return str(self).__getattribute__(name)

    def __len__(self):
        return len(self._characters)

    def __getitem__(self, index):
        return self._characters[index]

    def __setitem__(self, index, value):
        self._characters[index] = value

    def __getslice__(self, start, end=-1, stride=1):
        return str(self)[start:end:stride]


if __name__ == "__main__":
    m = MutableString("Hello")
    print m
    print len(m)
    print m.find("o")
    print m.find("x")
    print m.replace("e", "a") #translate to german ;-)
    print m
    print m[3]
    m[1] = "a"
    print m
    print m[:]

    copy1 = m
    copy2 = m[:]
    print m, copy1, copy2
    m[1] = "X"
    print m, copy1, copy2

免责声明:这只是一个示例,用于展示它如何工作并鼓励使用[:]. 它未经测试,不完整,可能性能非常糟糕

于 2013-01-21T07:03:48.783 回答
1

它们具有相同的值,但在处理可变对象时存在根本区别。

foo = [1, 2, 3]。您分配bar = foobaz = foo[:]。现在假设您要更改bar- bar.append(4)。您检查 的值foo,并且...

print foo
# [1, 2, 3, 4]

那额外的钱4是从哪里来的呢?这是因为您分配bar的身份foo所以当您更改一个时,您会更改另一个。你改变了baz- baz.append(5),但其他两个没有发生任何事情 - 那是因为你分配了to的副本foobaz

但是请注意,因为字符串是不可变的,所以没关系。

于 2013-01-21T07:04:28.913 回答
0

如果你有一个列表,结果会有所不同:

l = [1,2,3]
l1 = l
l2 = l[:]

l2 是 l(不同对象)的副本,而 l1 是 l 的别名,这意味着 l1[0]=7 也会修改 l,而 l2[1]=7 不会修改 l。

于 2013-01-21T07:05:01.423 回答
0

虽然引用对象和引用对象的副本对于像字符串这样的不可变对象没有区别,但对于可变对象(和可变方法),例如列表。

可变对象也是如此:

a = [1,2,3,4]
b = a
c = a[:]
a[0] = -1
print a    # will print [1,2,3,4]
print b    # will print [-1,2,3,4]
print c    # will print [1,2,3,4]

A visualization on pythontutor of the above example - http://goo.gl/Aswnl.

于 2013-01-21T07:13:17.940 回答