【问题标题】:Python : When is a variable passed by reference and when by value? [duplicate]Python:变量何时通过引用传递,何时通过值传递? [复制]
【发布时间】:2012-03-30 14:08:52
【问题描述】:

可能重复:
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,没有它可以吗?

【问题讨论】:

  • 一切都是按值传递的,但每个值都只是一个引用;)

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


【解决方案1】:

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

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

print locs

【讨论】:

    【解决方案2】:

    当你说

    loc = []
    

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

    也许你想要

    loc[:] = []
    

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

    【讨论】:

    • 我相信这最后一个例子就是 OP 想要的!
    【解决方案3】:

    在 Python 中,从引用或值的角度来思考是没有帮助的。两者都不正确。

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

    但由于在您的示例中,每个元素都是一个列表,您实际上可以 mutate 该元素,这将反映在原始列表中:

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

    【讨论】:

    • 阅读 Idiomatic Python 可能会有所帮助 - "other languages have variables, Python has labels." 其余部分也很好阅读。 ;)
    • 如何修改容器的每个元素? \
    • @Yugal 我上面写的哪一部分不清楚?
    • 一般来说,我只想处理我的容器的每个元素。那么,如何实现呢?如果一切都是一个标签,当实际想要编辑元素时似乎是一个缺点。
    • @YugalJindle :要修改 列表 中的元素,请使用方括号引用该列表中的项目。
    【解决方案4】:

    Effbot(又名 Fredrik Lundh)将 Python 的变量传递风格描述为按对象调用:http://effbot.org/zone/call-by-object.htm

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

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

    希望能为您澄清问题。

    【讨论】:

      【解决方案5】:

      为什么 loc 不是 locs 元素的引用?

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

      loc = []
      

      并不意味着“查看loc 命名的东西,并使其变成[]”。它不能意味着,因为 Python 对象不能做这样的事情。

      相反,它的意思是“使loc 不再是它当前名称的事物的名称,而是开始成为[] 的名称”。 (当然,它指的是那里提供的特定[],因为通常内存中可能有多个相同的对象。)

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

      【讨论】:

        【解决方案6】:

        Python 中的一切都是按值传递和赋值的,就像 Java 中的一切都按值传递和赋值一样。 Python 中的每个值都是对象的引用(指针)。对象不能是值。赋值总是复制值(这是一个指针);因此,两个这样的指针可以指向同一个对象。对象永远不会被复制,除非你明确地复制它们。

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

        【讨论】:

        • 在我看来 - 你描述得最好。只需告诉我问题更新的答案——你错过的那部分。
        • 那么整数和浮点数会发生什么?它们只是被认为是不可变的对象吗? python 如何管理它,因为我确信它不能在内存中保存所有可以想象的数字以供引用。
        • @AndrewS:整数和浮点数确实是不可变的(应该很明显,它们没有改变自身的方法)。我不确定您评论的第二部分是什么意思。
        • @AndrewS:也许它们是一样的,也许它们不是。为什么这有关系?这与赋值的可变性或语义无关。
        • @AndrewS 是的,floatint 对象是...对象。而且它们是不可变的。 Python 中的 Everything 是一个对象。您给出的示例的行为取决于实现,并且可以根据任何 python 版本进行更改,即使在次要版本更新中也是如此。但基本上,CPython 编译器通常会将不可变常量表达式优化为同一个对象。它发生的方式和时间取决于很多事情,同样,这是一个实现细节
        猜你喜欢
        • 2019-09-01
        • 2023-04-09
        • 2011-07-11
        • 1970-01-01
        • 2010-11-02
        相关资源
        最近更新 更多