Python为什么要使用[:] over =

时间:2021-02-01 19:00:45

I am just learning python and I am going though the tutorials on https://developers.google.com/edu/python/strings

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

Under the String Slices section

在“字符串切片”部分下

s[:] is 'Hello' -- omitting both always gives us a copy of the whole thing (this is the pythonic way to copy a sequence like a string or list)

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

Out of curiosity why wouldn't you just use an = operator?

出于好奇,你为什么不使用一个=运算符?

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

As far as I can tell both bar and foo have the same value.

据我所知,bar和foo都有相同的值。

4 个解决方案

#1


40  

= makes a reference, by using [:] you create a copy. For strings, which are immutable, this doesn't really matter, but for lists etc. it is crucial.

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

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

but:

>>> 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]

So why use it when dealing with strings? The built-in strings are immutable, but whenever you write a library function expecting a string, a user might give you something that "looks like a string" and "behaves like a string", but is a custom type. This type might be mutable, so it's better to take care of that.

那么为什么在处理字符串时使用它呢?内置字符串是不可变的,但每当你编写一个期望字符串的库函数时,用户可能会给你一些“看起来像字符串”和“表现得像字符串”的东西,但它是一种自定义类型。这种类型可能是可变的,因此最好照顾它。

Such a type might look like:

这样的类型可能如下所示:

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

Disclaimer: This is just a sample to show how it could work and to motivate the use of [:]. It is untested, incomplete and probably horribly performant

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

#2


1  

They have the same value, but there is a fundamental difference when dealing with mutable objects.

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

Say foo = [1, 2, 3]. You assign bar = foo, and baz = foo[:]. Now let's say you want to change bar - bar.append(4). You check the value of foo, and...

说foo = [1,2,3]。你指定bar = foo和baz = foo [:]。现在让我们说你要改变bar - bar.append(4)。你检查foo的值,然后......

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

Now where did that extra 4 come from? It's because you assigned bar to the identity of foo, so when you change one you change the other. You change baz - baz.append(5), but nothing has happened to the other two - that's because you assigned a copy of foo to baz.

现在,额外的4来自哪里?这是因为你为foo的身份分配了bar,所以当你改变一个时你改变了另一个。你改变了baz - baz.append(5),但是其他两个都没有发生 - 那是因为你给了baz一份foo的副本。

Note however that because strings are immutable, it doesn't matter.

但请注意,因为字符串是不可变的,所以无关紧要。

#3


0  

If you have a list the result is different:

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

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

l2 is a copy of l (different object) while l1 is an alias of l which means that l1[0]=7 will modify also l, while l2[1]=7 will not modify l.

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

#4


0  

While referencing an object and referencing the object's copy doesn't differ for an immutable object like string, they do for mutable objects (and mutable methods), for instance list.

虽然引用一个对象并引用该对象的副本对于像string这样的不可变对象没有区别,但它们对于可变对象(和可变方法),例如list。

Same thing on mutable objects:

可变对象上的相同内容:

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.

上面例子中pythontutor的可视化 - http://goo.gl/Aswnl。

#1


40  

= makes a reference, by using [:] you create a copy. For strings, which are immutable, this doesn't really matter, but for lists etc. it is crucial.

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

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

but:

>>> 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]

So why use it when dealing with strings? The built-in strings are immutable, but whenever you write a library function expecting a string, a user might give you something that "looks like a string" and "behaves like a string", but is a custom type. This type might be mutable, so it's better to take care of that.

那么为什么在处理字符串时使用它呢?内置字符串是不可变的,但每当你编写一个期望字符串的库函数时,用户可能会给你一些“看起来像字符串”和“表现得像字符串”的东西,但它是一种自定义类型。这种类型可能是可变的,因此最好照顾它。

Such a type might look like:

这样的类型可能如下所示:

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

Disclaimer: This is just a sample to show how it could work and to motivate the use of [:]. It is untested, incomplete and probably horribly performant

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

#2


1  

They have the same value, but there is a fundamental difference when dealing with mutable objects.

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

Say foo = [1, 2, 3]. You assign bar = foo, and baz = foo[:]. Now let's say you want to change bar - bar.append(4). You check the value of foo, and...

说foo = [1,2,3]。你指定bar = foo和baz = foo [:]。现在让我们说你要改变bar - bar.append(4)。你检查foo的值,然后......

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

Now where did that extra 4 come from? It's because you assigned bar to the identity of foo, so when you change one you change the other. You change baz - baz.append(5), but nothing has happened to the other two - that's because you assigned a copy of foo to baz.

现在,额外的4来自哪里?这是因为你为foo的身份分配了bar,所以当你改变一个时你改变了另一个。你改变了baz - baz.append(5),但是其他两个都没有发生 - 那是因为你给了baz一份foo的副本。

Note however that because strings are immutable, it doesn't matter.

但请注意,因为字符串是不可变的,所以无关紧要。

#3


0  

If you have a list the result is different:

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

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

l2 is a copy of l (different object) while l1 is an alias of l which means that l1[0]=7 will modify also l, while l2[1]=7 will not modify l.

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

#4


0  

While referencing an object and referencing the object's copy doesn't differ for an immutable object like string, they do for mutable objects (and mutable methods), for instance list.

虽然引用一个对象并引用该对象的副本对于像string这样的不可变对象没有区别,但它们对于可变对象(和可变方法),例如list。

Same thing on mutable objects:

可变对象上的相同内容:

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.

上面例子中pythontutor的可视化 - http://goo.gl/Aswnl。