Bukankah string Python tidak bisa diubah? Lalu mengapa a + “” + b bekerja?

109

Pemahaman saya adalah bahwa string Python tidak dapat diubah.

Saya mencoba kode berikut:

a = "Dog"
b = "eats"
c = "treats"

print a, b, c
# Dog eats treats

print a + " " + b + " " + c
# Dog eats treats

print a
# Dog

a = a + " " + b + " " + c
print a
# Dog eats treats
# !!!

Bukankah seharusnya Python mencegah penugasan? Saya mungkin melewatkan sesuatu.

Ada ide?

jason
sumber
55
String itu sendiri tidak dapat diubah tetapi labelnya dapat berubah.
mitch
6
Menetapkan nilai baru ke variabel yang ada benar-benar valid. Python tidak memiliki konstanta. Ini tidak tergantung dari mutabilitas tipe data.
Felix Kling
14
Anda mungkin ingin melihat id()fungsinya. aakan memiliki id yang berbeda sebelum dan sesudah tugas, yang menunjukkan bahwa itu menunjuk ke objek yang berbeda. Begitu juga dengan kode seperti b = aAnda akan menemukannya adan bakan memiliki id yang sama, menandakan mereka mereferensikan objek yang sama.
DRH
Tautan dari delnan persis seperti yang saya maksud.
mitch

Jawaban:

180

Pertama amenunjuk ke string "Anjing". Kemudian Anda mengubah variabel auntuk menunjuk ke string baru "Dog eats treats". Anda tidak benar-benar mengubah string "Anjing". String tidak dapat diubah, variabel dapat mengarah ke apa pun yang diinginkan.

Bort
sumber
34
Bahkan lebih meyakinkan untuk mencoba sesuatu seperti x = 'abc'; x [1] = 'x' di Python repl
xpmatteo
1
Jika Anda ingin lebih memahami bagian dalam, lihat jawaban saya. stackoverflow.com/a/40702094/117471
Bruno Bronosky
53

Objek string itu sendiri tidak dapat diubah.

Variabel, ayang menunjuk ke string, bisa berubah.

Mempertimbangkan:

a = "Foo"
# a now points to "Foo"
b = a
# b points to the same "Foo" that a points to
a = a + a
# a points to the new string "FooFoo", but b still points to the old "Foo"

print a
print b
# Outputs:

# FooFoo
# Foo

# Observe that b hasn't changed, even though a has.
Sebastian Paaske Tørholm
sumber
@jason mencoba jenis operasi yang sama dengan daftar (yang dapat berubah) untuk melihat perbedaan a.append (3) sesuai dengan a = a + "Foo"
jimifiki
1
@jimifiki a.append(3) tidak sama dengan a = a + 3. Ini bahkan tidak a += 3(penambahan di tempat sama dengan .extend, bukan dengan .append).
@ Delnan dan jadi, apa? Untuk menunjukkan bahwa string dan list berperilaku berbeda, Anda dapat mengasumsikan bahwa a = a + "Foo" sama dengan a.append (sesuatu). Bagaimanapun itu tidak sama. Jelas sekali. Apakah Anda lebih senang membaca a.extend ([sesuatu]) daripada a.append (sesuatu)? Saya tidak melihat perbedaan besar dalam konteks ini. Tapi mungkin aku melewatkan sesuatu. Thruth tergantung pada konteks
jimifiki
@jimifiki: Apa yang kamu bicarakan? +berperilaku sama untuk daftar dan string - ini digabungkan dengan membuat salinan baru dan tidak mengubah operan mana pun.
6
Hal yang sangat penting untuk diambil dari semua ini adalah bahwa string tidak memiliki append fungsi karena tidak dapat diubah.
Lily Chung
46

Variabel a menunjuk ke objek "Anjing". Yang terbaik adalah memikirkan variabel dengan Python sebagai tag. Anda dapat memindahkan tag untuk objek yang berbeda yang adalah apa yang Anda lakukan ketika Anda berubah a = "dog"ke a = "dog eats treats".

Namun, kekekalan mengacu pada objek, bukan tag.


Jika Anda mencoba a[1] = 'z'untuk membuat "dog"menjadi "dzg", Anda akan mendapatkan error:

TypeError: 'str' object does not support item assignment" 

karena string tidak mendukung penugasan item, sehingga string tidak dapat diubah.

chrtan
sumber
19

Sesuatu bisa berubah hanya jika kita dapat mengubah nilai yang disimpan di lokasi memori tanpa mengubah lokasi memori itu sendiri.

Triknya adalah: Jika Anda menemukan bahwa lokasi memori sebelum dan sesudah perubahan sama, itu bisa berubah.

Misalnya, daftar bisa berubah. Bagaimana?

>> a = ['hello']
>> id(a)
139767295067632

# Now let's modify
#1
>> a[0] = "hello new"
>> a
['hello new']
Now that we have changed "a", let's see the location of a
>> id(a)
139767295067632
so it is the same as before. So we mutated a. So list is mutable.

Sebuah string tidak bisa diubah. Bagaimana kita membuktikannya?

> a = "hello"
> a[0]
'h'
# Now let's modify it
> a[0] = 'n'
----------------------------------------------------------------------

kita mendapatkan

TypeError: objek 'str' tidak mendukung penugasan item

Jadi kami gagal memutasi string. Artinya string tidak bisa diubah.

Saat Anda menetapkan ulang, Anda mengubah variabel untuk menunjuk ke lokasi baru itu sendiri. Di sini Anda tidak melakukan mutasi string, tetapi mutasi variabel itu sendiri. Berikut ini adalah apa yang Anda lakukan.

>> a = "hello"
>> id(a)
139767308749440
>> a ="world"
>> id(a)
139767293625808

idsebelum dan sesudah penugasan ulang berbeda, jadi ini membuktikan bahwa Anda sebenarnya tidak bermutasi, tetapi mengarahkan variabel ke lokasi baru. Yang tidak memutasi string itu, tetapi memutasi variabel itu.

Harish Kayarohanam
sumber
11

Variabel hanyalah label yang menunjuk ke suatu objek. Objek tidak dapat diubah, tetapi Anda dapat membuat label mengarah ke objek yang sama sekali berbeda jika Anda mau.

jcollado.dll
sumber
8

Mempertimbangkan:

>>> a='asdf'
>>> a.__repr__
<method-wrapper '__repr__' of str object at 0x1091aab90>
>>> a='asdf'
>>> a.__repr__
<method-wrapper '__repr__' of str object at 0x1091aab90>
>>> a='qwer'
>>> a.__repr__
<method-wrapper '__repr__' of str object at 0x109198490>

Perhatikan bahwa lokasi memori hex tidak berubah ketika saya menyimpan nilai yang sama dalam variabel dua kali. Itu berubah ketika saya menyimpan nilai yang berbeda. String itu tidak bisa diubah. Bukan karena fanatisme, tetapi karena Anda membayar hukuman kinerja karena membuat objek baru dalam ingatan. Variabel ahanyalah label yang menunjuk ke alamat memori itu. Itu bisa diubah untuk menunjuk ke apapun.

Bruno Bronosky
sumber
7

Pernyataan tersebut a = a + " " + b + " " + cdapat dipecah berdasarkan petunjuk.

a + " "mengatakan beri saya apoin apa , yang tidak dapat diubah, dan tambahkan " "ke set kerja saya saat ini.

Penyimpanan:

working_set = "Dog "
a = "Dog" 
b = "eats"
c = "treats"

+ bmengatakan beri saya bpoin apa , yang tidak dapat diubah, dan tambahkan ke set kerja saat ini.

Penyimpanan:

working_set = "Dog eats"
a = "Dog" 
b = "eats"
c = "treats"

+ " " + cmengatakan tambahkan " "ke set saat ini. Lalu beri saya cpoin apa , yang tidak dapat diubah, dan tambahkan ke set kerja saat ini. Penyimpanan:

working_set = "Dog eats treats"
a = "Dog" 
b = "eats"
c = "treats"

Akhirnya, a =kata set pointer saya untuk menunjuk ke set yang dihasilkan.

Penyimpanan:

a = "Dog eats treats"
b = "eats"
c = "treats"

"Dog"direklamasi, karena tidak ada lagi pointer yang terhubung ke potongan memorinya. Kami tidak pernah mengubah bagian memori yang "Dog"berada, yang dimaksud dengan tidak dapat diubah. Namun, kita dapat mengubah label mana, jika ada, yang mengarah ke bagian memori tersebut.

Spencer Rathbun
sumber
6
l = [1,2,3]
print id(l)
l.append(4)
print id(l) #object l is the same

a = "dog"
print id(a)
a = "cat"
print id(a) #object a is a new object, previous one is deleted
pengguna744629
sumber
5

Ada perbedaan antara data dan label yang dikaitkan dengannya. Misalnya saat Anda melakukannya

a = "dog"

data "dog"dibuat dan diletakkan di bawah label a. Label bisa berubah tapi apa yang ada di memori tidak. Data "dog"akan tetap ada di memori (sampai pengumpul sampah menghapusnya) setelah Anda melakukannya

a = "cat"

Dalam program Anda asekarang ^ menunjuk ke ^ "cat"tetapi stringnya "dog"tidak berubah.

mitch
sumber
3

String Python tidak dapat diubah. Namun, aini bukan string: ini adalah variabel dengan nilai string. Anda tidak dapat mengubah string, tetapi dapat mengubah nilai variabel menjadi string baru.

Michael J. Barber
sumber
2

Variabel dapat mengarah ke mana saja yang mereka inginkan .. Kesalahan akan muncul jika Anda melakukan hal berikut:

a = "dog"
print a                   #dog
a[1] = "g"                #ERROR!!!!!! STRINGS ARE IMMUTABLE
GuruJeya
sumber
2

Objek string Python tidak dapat diubah. Contoh:

>>> a = 'tanim'
>>> 'Address of a is:{}'.format(id(a))
'Address of a is:64281536'
>>> a = 'ahmed'
>>> 'Address of a is:{}'.format(id(a))
'Address of a is:64281600'

Dalam contoh ini kita dapat melihat bahwa ketika kita menetapkan nilai yang berbeda dalam sebuah objek, objek baru dibuat.
Dan itu tidak bisa dimodifikasi. Contoh:

  >>> a[0] = 'c'
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
    **TypeError**: 'str' object does not support item assignment

Terjadi kesalahan.

Tanim_113
sumber
2

'mutable' berarti kita dapat mengubah konten string, 'immutable' berarti kita tidak dapat menambahkan string tambahan.

klik untuk bukti foto


sumber
1

>>> a = 'dogs'

>>> a.replace('dogs', 'dogs eat treats')

'dogs eat treats'

>>> print a

'dogs'

Tidak bisa diubah, bukan ?!

Bagian perubahan variabel telah dibahas.

Lohit Bisen
sumber
1
Ini tidak membuktikan atau menyangkal mutabilitas string python, hanya saja replace()metode tersebut mengembalikan string baru.
Brent Hronik
1

Pertimbangkan tambahan ini untuk contoh Anda

 a = "Dog"
 b = "eats"
 c = "treats"
 print (a,b,c)
 #Dog eats treats
 d = a + " " + b + " " + c
 print (a)
 #Dog
 print (d)
 #Dog eats treats

Salah satu penjelasan lebih tepat yang saya temukan di blog adalah:

Dalam Python, (hampir) semuanya adalah objek. Apa yang biasa kita sebut sebagai "variabel" di Python lebih tepat disebut nama. Demikian juga, "penugasan" sebenarnya adalah pengikatan nama ke objek. Setiap binding memiliki cakupan yang menentukan visibilitasnya, biasanya blok asal nama tersebut.

Misalnya:

some_guy = 'Fred'
# ...
some_guy = 'George'

Saat nanti kita mengatakan some_guy = 'George', objek string yang berisi 'Fred' tidak terpengaruh. Kami baru saja mengubah pengikatan nama some_guy. Namun, kami belum mengubah objek string 'Fred' atau 'George'. Sejauh yang kami ketahui, mereka mungkin hidup tanpa batas.

Tautan ke blog: https://jeffknupp.com/blog/2012/11/13/is-python-callbyvalue-or-callbyreference-neither/

7to4
sumber
1

Menambahkan sedikit lebih banyak pada jawaban yang disebutkan di atas.

id variabel berubah setelah penugasan ulang.

>>> a = 'initial_string'
>>> id(a)
139982120425648
>>> a = 'new_string'
>>> id(a)
139982120425776

Artinya kita telah mengubah variabel auntuk menunjuk ke string baru. Sekarang ada dua objek string (str):

'initial_string'dengan id= 139982120425648

dan

'new_string'dengan id= 139982120425776

Perhatikan kode di bawah ini:

>>> b = 'intitial_string'
>>> id(b)
139982120425648

Sekarang, btunjuk ke 'initial_string'dan memiliki yang sama idseperti asebelumnya.

Jadi, 'intial_string'belum bermutasi.

Rahul Madiwale
sumber
0

Meringkas:

a = 3
b = a
a = 3+2
print b
# 5

Tidak tetap:

a = 'OOP'
b = a
a = 'p'+a
print b
# OOP

Kekal:

a = [1,2,3]
b = range(len(a))
for i in range(len(a)):
    b[i] = a[i]+1

Ini adalah kesalahan dalam Python 3 karena tidak dapat diubah. Dan bukan kesalahan di Python 2 karena jelas itu tidak bisa diubah.

pjf
sumber
0

Fungsi id()bawaan mengembalikan identitas objek sebagai integer. Bilangan bulat ini biasanya sesuai dengan lokasi objek di memori.

\>>a='dog'
\>>print(id(a))

139831803293008

\>>a=a+'cat'
\>>print(id(a))

139831803293120

Awalnya, 'a' disimpan di lokasi memori 139831803293008, karena objek string tidak dapat diubah dalam python jika Anda mencoba mengubah dan menetapkan ulang referensi akan dihapus dan akan menjadi penunjuk ke lokasi memori baru (139831803293120).

pelajar5060
sumber
0
a = 'dog'
address = id(a)
print(id(a))

a = a + 'cat'
print(id(a))      #Address changes

import ctypes
ctypes.cast(address, ctypes.py_object).value    #value at old address is intact
10xAI
sumber
2
Meskipun kode ini dapat menyelesaikan masalah OP, yang terbaik adalah menyertakan penjelasan tentang bagaimana kode Anda mengatasi masalah OP. Dengan cara ini, pengunjung selanjutnya dapat belajar dari postingan Anda, dan menerapkannya ke kode mereka sendiri. SO bukanlah layanan pengkodean, tetapi sumber daya untuk pengetahuan. Selain itu, jawaban lengkap dan berkualitas tinggi kemungkinan besar akan dipilih. Fitur ini, bersama dengan persyaratan bahwa semua posting berdiri sendiri, adalah beberapa kekuatan SO sebagai platform, yang membedakannya dari forum. Anda dapat mengedit untuk menambahkan info tambahan & / atau untuk melengkapi penjelasan Anda dengan dokumentasi sumber
SherylHohman
-1

Gambar ini memberikan jawabannya. Mohon dibaca.

masukkan deskripsi gambar di sini

Wen Qi
sumber
-1

Kami baru saja menggabungkan dua nilai string. Kami tidak pernah mengubah nilai (a). Sekarang (a) mewakili blok memori lain yang memiliki nilai "dogdog". Karena di backend, satu variabel tidak pernah merepresentasikan dua blok memori pada waktu yang bersamaan. Nilai (a) sebelum penggabungan adalah "anjing". Tapi setelah itu (a) mewakili "dogdog", karena sekarang (a) di rep backend. blok yang memiliki nilai "dogdog". Dan "anjing" adalah rep. oleh (b) dan "anjing" tidak dihitung sebagai nilai sampah sampai (b) mewakili "anjing".

Kebingungannya adalah kita merepresentasikan blok memori (yang berisi data atau info.) Di backend dengan nama variabel yang sama.

dineshmehta
sumber
-2

Anda dapat membuat array numpy tidak dapat diubah dan menggunakan elemen pertama:

numpyarrayname[0] = "write once"

kemudian:

numpyarrayname.setflags(write=False)

atau

numpyarrayname.flags.writeable = False
PauluaP
sumber