Python:何时是通过引用传递的变量和何时按值传递?

时间:2012-03-14 05:36:37

标签: python reference pass-by-reference pass-by-value

  

可能重复:
  Python: How do I pass a variable by reference?

我的代码:

locs = [ [1], [2] ]
for loc in locs:
    loc = []

print locs
# prints => [ [1], [2] ]

为什么loc没有引用locs的元素?

Python:除非明确复制,否则所有内容都将作为引用传递[这不是真的吗? ]

请解释.. python如何决定引用和复制

更新:

怎么办?

def compute(ob):
   if isinstance(ob,list): return process_list(ob)
   if isinstance(ob,dict): return process_dict(ob)

for loc in locs:
   loc = compute(loc)  # What to change here to make loc a reference of actual locs iteration ?
  • locs必须包含最终处理的响应!
  • 我不想使用enumerate,没有它可以吗?

6 个答案:

答案 0 :(得分:49)

Effbot(又名Fredrik Lundh)将Python的变量传递样式描述为逐个调用:http://effbot.org/zone/call-by-object.htm

对象在堆上分配,指向它们的指针可以在任何地方传递。

  • 当您进行x = 1000之类的分配时,会创建一个字典条目,将当前名称空间中的字符串“x”映射到指向包含一千个整数对象的指针。
  • 使用x = 2000更新“x”时,会创建一个新的整数对象,并更新字典以指向新对象。旧的一千个对象没有变化(可能存在也可能不存在,具体取决于是否有其他东西引用该对象)。
  • 当您执行y = x等新作业时,会创建一个新词典条目“y”,指向与“x”条目相同的对象。
  • 像字符串和整数这样的对象是不可变的。这只是意味着没有方法可以在创建对象后更改对象。例如,一旦创建了整数对象一千,它就永远不会改变。通过创建新的整数对象来完成数学。
  • 像列表这样的对象 mutable 。这意味着可以通过指向对象的任何内容来更改对象的内容。例如,x = []; y = x; x.append(10); print y将打印[10]。空列表已创建。 “x”和“y”都指向同一个列表。 append 方法改变(更新)列表对象(如向数据库添加记录),结果对“x”和“y”都可见(正如数据库更新可见与该数据库的每个连接)。

希望能为您澄清问题。

答案 1 :(得分:23)

Python中的所有内容都按值传递和分配,就像在Java中传递所有内容并按值分配一样。 Python中的每个值都是对象的引用(指针)。对象不能是值。赋值总是复制值(这是一个指针);因此,两个这样的指针可以指向同一个对象。除非您正在做一些明确的复制对象,否则永远不会复制对象。

对于您的情况,循环的每次迭代都会将列表的元素分配给变量loc。然后,您将其他内容分配给变量loc。所有这些值都是指针;你正在分配指针;但是你不会以任何方式影响任何物体。

答案 2 :(得分:8)

在Python中无法根据引用或值进行思考。两者都不正确。

在Python中,变量只是名称。在for循环中,loc只是一个指向列表中当前元素的名称。执行loc = []只需将名称loc重新绑定到另一个列表,只保留原始版本。

但是因为在你的例子中,每个元素都是一个列表,你实际上可以 mutate 那个元素,这将反映在原始列表中:

for loc in locs:
    loc[0] = loc[0] * 2

答案 3 :(得分:5)

当你说

loc = []

您正在将loc变量重新绑定到新创建的空列表

也许你想要

loc[:] = []

将loc的切片(恰好是整个列表)分配给空列表

答案 4 :(得分:2)

一切都是通过对象传递的。重新绑定和变异是不同的操作。

locs = [ [1], [2] ]
for loc in locs:
    del loc[:]

print locs

答案 5 :(得分:2)

  

为什么loc不能引用loc的元素?

。或者至少,它与Python中的每个其他变量具有相同的意义。 Python变量是名称,而不是存储loc是一个用于引用[[1,2], [3,4]]元素的名称,而locs是一个引用整个结构的名称。

loc = []

并不意味着“查看loc命名的内容,并将其转换为[]”。 不能意味着,因为Python对象不能这样的事情。

相反,它意味着“导致loc停止成为其当前名称的事物的名称,并开始代之以[]的名称”。 (当然,它意味着在那里提供的特定[],因为通常在内存中可能有几个对象是相同的。)

当然,locs的内容不会因此而改变。