从这个链接:如何通过引用传递变量?,我们知道,当将字符串(一个不可变类型变量)作为参数传递给函数时,Python会复制它,但如果字符串很大,这将浪费内存。在许多情况下,我们需要使用函数来封装一些字符串操作,因此我想知道如何更有效地实现?
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 的处理方式是将字符串保存在列表中,一旦拥有所有段落就将它们连接起来。
swap(a, b)
)占用了。 - user395760swap(&a, &b)
并将其称为按引用传递。然而,在Python中实际上你所做的与此非常相似。你可以将对象传入函数并在函数中更改该对象,但无法更改“指针”指向的位置。唯一的区别是Python具有不可变对象,因此对于不可变对象,你不允许更改“指针”引用的对象。无论如何,我从来不清楚应该如何称呼它(对于Python或C)。 - mgilsonPython确实是通过引用传递字符串的。请注意,具有相同内容的两个字符串被认为是相同的:
a = 'hello'
b = 'hello'
a is b # True
当b被分配一个值时,如果该值已经存在于内存中,则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
底线:
你不能真正地改变一个字符串。这对于可能所有的编程语言都是一样的(但请不要引用我)。 当你将字符串作为参数传递时,你传递的是一个引用。当你改变它的值时,你改变了变量指向内存中另一个位置的指针。但当你改变一个变量的引用时,指向相同地址的其他变量自然会保留他们原来持有的旧值(引用)。 希望这个解释足够清晰易懂。
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
但是对字符串的操作总是返回一个新的字符串对象。
如果想要潜在地改变传入的某个值,请将其包装在字典或列表中:
这不会改变 s 的值。
def x(s):
s += 1
这会改变 s:
def x(s):
s[0] += 1
这是唯一的“按引用传递”的方法。
def modify_string( t ):
the_string = t[0]
# do stuff
modify_string( ["my very long string"] )
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'
只需像处理其他参数一样传递即可。内容不会被复制,只有引用会被传递。