从这个链接:我如何通过引用传递变量?我们知道,当Python作为参数传递给函数时,Python将复制一个字符串(一个不可变类型变量),但我认为如果字符串很大,它将浪费内存.在许多情况下,我们需要使用函数来包装字符串的一些操作,所以我想知道如何更有效地执行它?
Ste*_*ski 29
Python不会复制传递给函数的对象(包括字符串):
>>> def foo(s):
... return id(s)
...
>>> x = 'blah'
>>> id(x) == foo(x)
True
Run Code Online (Sandbox Code Playgroud)
如果需要"修改"函数中的字符串,请返回新字符串并将其分配回原始名称:
>>> def bar(s):
... return s + '!'
...
>>> x = 'blah'
>>> x = bar(x)
>>> x
'blah!'
Run Code Online (Sandbox Code Playgroud)
不幸的是,当对大字符串进行小的更改时,这可能是非常低效的,因为大字符串被复制.解决这个问题的pythonic方法是在列表中保存字符串,并在拥有所有部分后将它们连接在一起.
Python确实通过引用传递字符串。请注意,具有相同内容的两个字符串被视为相同:
a = 'hello'
b = 'hello'
a is b # True
Run Code Online (Sandbox Code Playgroud)
由于当 b 被赋值时,并且该值已存在于内存中,因此它使用字符串的相同引用。请注意另一个事实,如果字符串是动态创建的,即通过字符串操作(即串联)创建的,则新变量将引用同一字符串的新实例:
c = 'hello'
d = 'he'
d += 'llo'
c is d # False
Run Code Online (Sandbox Code Playgroud)
话虽这么说,创建一个新字符串将在内存中分配一个新字符串并返回新字符串的引用,但使用当前创建的字符串将重用相同的字符串实例。因此,将字符串作为函数参数传递将通过引用传递它,或者换句话说,将传递字符串在内存中的地址。
现在到了您正在寻找的点 - 如果您更改函数内部的字符串,函数外部的字符串将保持不变,这源于字符串不可变性。更改字符串意味着在内存中分配一个新字符串。
a = 'a'
b = a # b will hold a reference to string a
a += 'a'
a is b # False
Run Code Online (Sandbox Code Playgroud)
底线:
你不能真正改变一个字符串。也许与其他所有编程语言相同(但不要引用我的话)。当您将字符串作为参数传递时,您就传递了一个引用。当您更改它的值时,您将变量更改为指向内存中的另一个位置。但是,当您更改变量的引用时,指向同一地址的其他变量自然会保留它们所持有的旧值(引用)。希望解释足够清楚
如果您想更改传入的内容的值,请将其包装在字典或列表中:
这不会改变
def x(s):
s += 1
Run Code Online (Sandbox Code Playgroud)
这确实改变了:
def x(s):
s[0] += 1
Run Code Online (Sandbox Code Playgroud)
这是“通过引用传递”的唯一方法。
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
Run Code Online (Sandbox Code Playgroud)
但是对字符串的操作总是返回一个新的字符串对象。
def modify_string( t ):
the_string = t[0]
# do stuff
modify_string( ["my very long string"] )
Run Code Online (Sandbox Code Playgroud)
小智 5
将字符串包装到一个类中将使其通过引用传递:
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'
Run Code Online (Sandbox Code Playgroud)