25

私はちょうどPythonを学んでいて、https://developers.google.com/edu/python/stringsのチュートリアルを進めています

String Slicesセクションの下

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 = foo、、を割り当てbaz = foo[:]ます。ここで、変更したいとしますbar- bar.append(4)。の値を確認し、foo...

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

さて、その余分な4ものはどこから来たのですか?これは、のIDを割り当てbarたためです。したがって、一方を変更すると、もう一方も変更されます。を変更しますが、他の2つには何も起こりません。これは、のコピーをに割り当てたためです。foobazbaz.append(5)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]

上記の例の pythontutor での視覚化 - http://goo.gl/Aswnl

于 2013-01-21T07:13:17.940 に答える