2017-07-07 184 views
5

我有一个关于python函数范围的问题。我已经包含了一个演示我遇到的问题的示例。Python函数范围

fun0重新定义了变量c的列表中的第一个条目。这种变化反映在fun0之外,即使我没有从fun0返回任何值。

FUN1重新定义了可变Ç完全,但是变化并不的FUN1外侧反射。同样,fun2重新定义了c,并且该更改未反映在之外fun2

我的问题是,为什么fun0修改在主要功能VAL3,而FUN1FUN2不修改分别VAL4val7,?

def fun0(a, b, c): 
    c[0] = a[0] + b[0] 
    return 

def fun1(a, b, c): 
    c = a[0] + b[0] 
    return 

def fun2(a, b, c): 
    c = a + b 
    return 

def main(): 
    val1 = ['one'] 
    val2 = ['two'] 
    val3 = [''] 
    fun0(val1, val2, val3) 
    print val3 

    val4 = [] 
    fun1(val1, val2, val4) 
    print val4 

    val5 = 1 
    val6 = 1 
    val7 = 0 
    fun2(val5, val6, val7) 
    print val7 
    return 

if __name__=='__main__': 
    main() 
+4

列表是可变的,你可以修改它们的元素,它会影响每个人的参考。当你重新分配它时,你正在创建一个新的参考。 – byxor

+0

这很奇怪,我把其他代码片段称为“所有人”。也许人性化的代码是我更好地理解它的方式。 – byxor

回答

1

我的问题是,为什么fun0修改主函数中的val3,而fun1和fun2分别不修改val4和val7?

这是因为Python传递参数的方式。

将参数传递给函数时,Python通过赋值来传递参数。这意味着它将参数引用绑定到参数名称。这是参数和参数名称相关的唯一方法。在第一个示例中,您只需传递对val3的引用,并且由于val3c都引用了相同的列表对象,所以更改反映在两个名称中。

但是,当您在函数内部重新分配c时,您将引用替换为列表c被持有并重新分配为c的新引用。

+0

就范围而言,我的示例中的函数可以访问输入参数,局部变量和全局变量。如果一个参数是可变的,那么函数可以通过引用改变它的值,反过来,这些改变发生在函数的范围之外(如果我错了,或者不准确,就纠正我)。 – shoe02

+0

是的,你所说的一切都非常正确。我会做的唯一的评论是默认情况下变量不是全局的。 [详情请看这里](https://stackoverflow.com/questions/10588317/python-function-global-variables)。 –

+0

好吧,所以当我审查代码时,如果输入参数是可变的,我也会记住。感谢您的帮助! – shoe02

2

它与存储列表和变量的方式有关。您可以修改函数中的列表,因为它们是可变对象。但是,如果您执行c = a[0] + b[0],则会在fun1fun2之间创建一个局部变量,该变量保持在函数范围内。

0

Cary Shindell是绝对正确的。此外,如果您想保存更新的值,那么您可以如何更改您的代码来执行此操作,因为我在python 3.6.1中测试了这一点,所以我更改了打印语句。好问题,但。

def main(): 
    val1 = ['one'] 
    val2 = ['two'] 
    val3 = [''] 
    fun0(val1, val2, val3) 
    print(val3) 

    val4 = [] 
    val4 = fun1(val1, val2, val4) 
    print(val4) 

    val5 = 1 
    val6 = 1 
    val7 = 0 
    val7 = fun2(val5, val6, val7) 
    print(val7) 
    return 
1

从技术上讲,当你传递一个函数的参数时,你传递的是副本,而不是原来的。现在,传递一个列表和传递变量是有区别的。一个列表保存了一个变量持有一个值的同时对其他对象的引用。因此,在传递列表时,即使它被复制,它仍然引用相同的对象,并且可以在函数内进行更改,但是当传递一个变量时,复制的对象与原始内容无关。希望这是有道理的。

0

如前所述,列表是可变的。如果你通过一个列表并修改它,你就可以在任何地方进行。 这适用于fun0中的所有列表。

fun2您传递没有列表,因此c计算在fun2内,但在外部不可用。

我不知道fun1,但我认为你是一个新的变量,不可在外面作为fun2覆盖c