32

从此链接:如何通过引用传递变量?,我们知道,Python在作为参数传递给函数的时候会复制一个字符串(一个不可变的类型变量),但是我认为如果字符串很大的话会浪费内存。很多情况下,我们需要用函数来包装一些对字符串的操作,所以想知道怎么做更有效?

4

7 回答 7

39

Python 不会复制传递给函数的对象(包括字符串):

>>> def foo(s):
...     return id(s)
...
>>> x = 'blah'
>>> id(x) == foo(x)
True

如果您需要在函数中“修改”字符串,请返回新字符串并将其分配回原始名称:

>>> def bar(s):
...     return s + '!'
...
>>> x = 'blah'
>>> x = bar(x)
>>> x
'blah!'

不幸的是,当对大字符串进行小的更改时,这可能非常低效,因为大字符串会被复制。处理这个问题的pythonic方法是将字符串保存在一个列表中,并在你拥有所有部分后将它们连接在一起。

于 2012-11-28T15:46:49.930 回答
7

Python确实通过引用传递了一个字符串。请注意,具有相同内容的两个字符串被认为是相同的:

a = 'hello'
b = 'hello'
a is b        # True

由于当 b 被一个值赋值,并且该值已经存在于内存中时,它使用相同的字符串引用。请注意另一个事实,如果字符串是动态创建的,即使用字符串操作(即连接)创建,新变量将引用同一字符串的新实例:

c = 'hello'
d = 'he'
d += 'llo'
c is d        # False

话虽如此,创建一个新字符串将在内存中分配一个新字符串并返回一个新字符串的引用,但使用当前创建的字符串将重用相同的字符串实例。因此,将字符串作为函数参数传递通过引用传递,或者换句话说,将传递字符串在内存中的地址。

现在到了您正在寻找的地方-如果您更改函数内部的字符串,则函数外部的字符串将保持不变,这源于字符串的不变性。更改字符串意味着在内存中分配一个新字符串。

a = 'a'
b = a    # b will hold a reference to string a
a += 'a'
a is b   # False

底线:

你不能真正改变一个字符串。可能与其他所有编程语言相同(但不要引用我的话)。当您将字符串作为参数传递时,您传递了一个引用。当您更改它的值时,您将变量更改为指向内存中的另一个位置。但是当你改变一个变量的引用时,其他指向同一个地址的变量自然会保留它们持有的旧值(引用)。希望解释足够清楚

于 2018-06-14T22:11:39.833 回答
5
In [7]: strs="abcd"

In [8]: id(strs)
Out[8]: 164698208

In [9]: def func(x):
    print id(x)
    x=x.lower() #perform some operation on string object, it returns a new object
    print id(x)
   ...:     

In [10]: func(strs)
164698208              # same as strs, i.e it actually passes the same object 
164679776              # new object is returned if we perform an operation
                       # That's why they are called immutable  

但是对字符串的操作总是返回一个新的字符串对象。

于 2012-11-28T15:48:24.680 回答
5
def modify_string( t ):
  the_string = t[0]
  # do stuff

modify_string( ["my very long string"] )
于 2012-11-28T16:20:11.087 回答
4

如果您想潜在地更改传入的值,请将其包装在 dict 或列表中:

这不会改变

def x(s):
  s += 1

这确实改变了 s:

def x(s):
  s[0] += 1

这是“通过引用传递”的唯一方法。

于 2019-12-18T17:33:37.410 回答
2

将字符串包装成一个类将使其通过引用传递:

    class refstr:
       "wrap string in object, so it is passed by reference rather than by value"
       def __init__(self,s=""):
          self.s=s
       def __add__(self,s):
          self.s+=s
          return self
       def __str__(self):
          return self.s

    def fn(s):
       s+=" world"

    s=refstr("hello")
    fn(s) # s gets modified because objects are passed by reference
    print(s) #returns 'hello world' 
于 2020-02-28T12:34:12.650 回答
1

只需像传递任何其他参数一样传递它。内容不会被复制,只有引用会。

于 2012-11-28T15:46:50.990 回答