代码之家  ›  专栏  ›  技术社区  ›  Mwspencer

向Python的不可变字符串添加字符[重复]

  •  -1
  • Mwspencer  · 技术社区  · 5 年前

    我的理解是Python字符串是不可变的。

    我尝试了以下代码:

    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
    # !!!
    

    Python不应该阻止赋值吗?我可能错过了什么。

    知道吗?

    0 回复  |  直到 7 年前
        1
  •  219
  •   Bort    13 年前

    弗斯特 a 他指着绳子“狗”。然后你改变了变量 指向一个新的字符串“狗吃零食”。你实际上并没有对字符串“狗”进行突变。字符串是不可变的,变量可以指向它们想要的任何东西。

        2
  •  68
  •   Sebastian Paaske Tørholm    13 年前

    字符串对象本身是不可变的。

    变量, a ,指向字符串,是可变的。

    考虑:

    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.
    
        3
  •  53
  •   glglgl John Dvorak    13 年前

    变量a指向对象“Dog”。最好把Python中的变量看作一个标签。您可以将标签移动到不同的对象,这是您更改时所做的操作 a = "dog" a = "dog eats treats" .

    然而,不变性是指对象,而不是标签。


    如果你尝试过 a[1] = 'z' 使 "dog" 进入之内 "dzg" ,您将得到错误:

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

    因为字符串不支持项赋值,所以它们是不可变的。

        4
  •  30
  •   Community CDub    7 年前

    只有当我们能够更改内存位置中保存的值而不更改内存位置本身时,某些东西才是可变的。

    诀窍是:如果你发现更改前后的内存位置是相同的,那么它是可变的。

    例如,list是可变的。怎么用?

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

    字符串是不可变的。我们如何证明这一点?

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

    我们得到

    TypeError: 'str' object does not support item assignment

    因此,我们未能对字符串进行变异。这意味着字符串是不可变的。

    在重新分配时,您可以更改变量以指向新位置本身。在这里,您没有对字符串进行突变,而是对变量本身进行了突变。以下是你正在做的事情。

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

    id 重新分配之前和之后是不同的,所以这证明你实际上并没有发生变异,而是将变量指向新的位置。这不是对字符串进行变异,而是对变量进行变异。

        5
  •  14
  •   Moot    7 年前

    考虑:

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

    请注意,当我在变量中存储相同的值两次时,十六进制内存位置没有改变。当我存储不同的值时,它确实发生了变化。字符串是不可变的。不是因为狂热,而是因为在内存中创建新对象会带来性能损失。变量 a 只是指向该内存地址的标签。它可以被修改以指向任何东西。

        6
  •  12
  •   glglgl John Dvorak    13 年前

    变量只是指向对象的标签。对象是不可变的,但如果你愿意,你可以让标签指向一个完全不同的对象。

        7
  •  7
  •   Spencer Rathbun    13 年前

    声明 a = a + " " + b + " " + c 可以根据指针进行分解。

    a + " " 说给我什么 a 指向,无法更改,并添加 " " 我目前的工作环境。

    内存:

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

    + b 说给我什么 b 指向(无法更改),并将其添加到当前工作集中。

    内存:

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

    + " " + c 说add " " 到当前设置。那给我什么 c 指向(无法更改),并将其添加到当前工作集中。 内存:

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

    最后, a = 设置我的指针指向结果集。

    内存:

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

    "Dog" 被回收,因为没有更多的指针连接到它的内存块。我们从未修改过内存部分 “狗” 居住在,这就是不可变的意思。然而,我们可以更改哪些标签(如果有的话)指向该内存部分。

        8
  •  7
  •   mitch    13 年前

    数据与其关联的标签之间存在差异。例如,当你这样做的时候

    a = "dog"
    

    数据 "dog" 创建并放置在标签下 a 标签可以更改,但内存中的内容不会更改。数据 “狗” 执行此操作后,它仍将存在于内存中(直到垃圾收集器将其删除)

    a = "cat"
    

    在您的程序中 现在^指向^ "cat" 但是绳子 “狗” 没有改变。

        9
  •  6
  •   user744629    13 年前
    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
    
        10
  •  4
  •   Michael J. Barber    13 年前

    Python字符串是不可变的。然而, a 不是字符串:它是一个具有字符串值的变量。您不能更改字符串,但可以将变量的值更改为新字符串。

        11
  •  4
  •   Tanim_113    7 年前

    Python字符串对象是不可变的。 例子:

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

    在这个例子中,我们可以看到,当我们在a中分配不同的值时,它不会改变。创建了一个新对象。
    而且它不能被修改。 例子:

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

    发生错误。

        12
  •  2
  •   utapyngo    8 年前

    变量可以指向他们想要的任何地方。。 如果执行以下操作,将抛出错误:

    a = "dog"
    print a                   #dog
    a[1] = "g"                #ERROR!!!!!! STRINGS ARE IMMUTABLE
    
        13
  •  2
  •   user10052573 user10052573    6 年前

    “mutable”意味着我们可以更改字符串的内容, “immutable”意味着我们不能添加额外的字符串。

    click for photo proof

        14
  •  2
  •   10xAI    4 年前
    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
    
        15
  •  1
  •   Peter Mortensen icecrime    8 年前

    >>> a = 'dogs'

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

    'dogs eat treats'

    >>> print a

    'dogs'

    不可改变,不是吗?!

    变量变化部分已经讨论过了。

        16
  •  1
  •   Community CDub    4 年前

    将此添加到您的示例中

     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
    

    我在博客中发现的一个更精确的解释是:

    在Python中,(几乎)一切都是对象。在Python中,我们通常所说的“变量”更恰当地称为名称。同样,“赋值”实际上是将名称绑定到对象。每个绑定都有一个定义其可见性的范围,通常是名称来源的块。

    如:

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

    当我们稍后说some_guy='George'时,包含'Fred'的字符串对象不受影响。我们刚刚更改了some_guy名称的绑定。然而,我们没有更改“Fred”或“George”字符串对象。就我们而言,他们可能会无限期地活着。

    博客链接: https://jeffknupp.com/blog/2012/11/13/is-python-callbyvalue-or-callbyreference-neither/

        17
  •  1
  •   Rahul Madiwale    7 年前

    对上述答案再加一点。

    id 变量在重新分配后发生变化。

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

    这意味着我们已经对变量进行了突变 a 指向一个新字符串。现在存在 string (str)对象:

    'initial_string' 具有 身份证件 = 139982120425648

    'new_string' 具有 身份证件 = 139982120425776

    考虑以下代码:

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

    现在, b 指向 'initial_string' 并且具有相同的 身份证件 作为 在重新分配之前。

    因此 'intial_string' 没有发生突变。

        18
  •  1
  •   nyconing learner5060    5 年前

    内置功能 id() 以整数形式返回对象的标识。这个整数通常对应于对象在内存中的位置。

    \>>a='dog'
    \>>print(id(a))
    
    139831803293008
    
    \>>a=a+'cat'
    \>>print(id(a))
    
    139831803293120
    

    最初,'a'存储在139831803293008内存位置,因为如果您尝试修改和重新分配引用,python中的字符串对象是不可变的。该引用将被删除,并将成为指向新内存位置的指针(13983180329 3120)。

        19
  •  0
  •   Peter Mortensen icecrime    8 年前

    总结:

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

    不是不可变的:

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

    免疫:

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

    这是Python 3中的一个错误,因为它是不可变的。Python 2中没有错误,因为它显然不是不可变的。

        20
  •  -1
  •   dineshmehta    5 年前

    我们只是将两个字符串值连接起来。我们从不改变(a)的值。刚才(a)表示另一个具有“狗”值的内存块。因为在后端,一个变量永远不会同时表示两个内存块。连接前(a)的值是“dog”。但在那之后(a)表示“狗”,因为现在(a)在后端表示具有“狗”值的块。“dog”是由(b)表示的,在(b)代表“dog”之前,“dog”不会被计为垃圾值。

    令人困惑的是,我们在后端用相同的变量名表示内存块(包含数据或信息)。

        21
  •  -2
  •   PauluaP    7 年前

    你可以使numpy数组不可变,并使用第一个元素:

    numpyarrayname[0] = "write once"
    

    那么:

    numpyarrayname.setflags(write=False)
    

    numpyarrayname.flags.writeable = False
    
        22
  •  -2
  •   Wen Qi    6 年前

    这张图片给出了答案。请仔细阅读。

    enter image description here