【问题标题】:What is the scope of argument variables in python?python中参数变量的范围是什么?
【发布时间】:2021-04-29 07:15:34
【问题描述】:

考虑以下情况:

案例一:

def fun(arg):
    
    arg += 1
    
my_var = 1
fun(my_var)
print(my_var)
>> 1

案例 2:

def fun(arg):
    
    arg += [4]
    
my_var = [1,2,3]
fun(my_var)
print(my_var)
>> [1, 2, 3, 4]

案例 3:

def fun(arg):
    
    arg = arg + [4]
    
my_var = [1,2,3]
fun(my_var)
print(my_var)
>> [1, 2, 3]

案例 4:

def fun(arg):
    
    print(arg)

fun("Hi")
print(arg)
>> Hi
Traceback (most recent call last):
  File "<string>", line 8, in <module>
NameError: name 'arg' is not defined

案例 4 表明参数变量的范围位于函数内。情况 1 和 3 支持,因为函数内 arg 变量的更改不会反映在全局参数中。

但是为什么情况 2 会发生呢?当我使用 append 而不是 += 时,我注意到了同样的事情。发生在 arg 上的更改不应该对从不同范围调用函数的变量产生任何影响吗?

任何帮助表示赞赏。提前致谢。

【问题讨论】:

  • 将新值赋给变量(案例 1,3)不同于 mutating 值(恰好被变量“持有”)(案例 2) .或者换句话说:在情况 1 和 3 中,您正在读取和写入 arg。在案例 2 中,您只是从 arg 中读取。
  • += 对于列表来说有点奇怪,因为它会改变左边的操作数。 mylist += Xmylist = mylist + X 做了不同的事情。见Why does += behave unexpectedly on lists?
  • 这是 Robert Heaton 对函数作用域的一个很好的整体解释,JFYI robertheaton.com/2014/02/09/…

标签: python function scope


【解决方案1】:

答案很简单:函数参数是局部变量!

更多观察:

= 是赋值运算符并重新绑定一个变量。这永远不会改变对象(异常切片分配)。

+= 是它自己的运算符,并被实现为可变类型的突变。您可以通过实现__iadd__ dunder 方法为您自己的类型实现其行为。 因此,一般来说,a = a + b等同于a += b

对于列表,a += b 对应于 a.extend(b)。另一方面,a + b 创建一个 new 列表对象,a = a + b 将变量 a 重新绑定到该新对象。

【讨论】:

    【解决方案2】:

    案例 2 是唯一在实例上使用变异方法的情况。这会影响传递的参数。

    其他人什么都不做,或者只是重新分配参数。 python中的赋值只影响被赋值的变量,而不影响仍然引用前一个实例的其他变量。

    必须链接到Ned Batchelder

    【讨论】:

      【解决方案3】:

      Python 允许您通过为变量赋值来创建变量,而无需预先声明变量。分配给变量的值决定了变量的类型。

      如果你在每个函数上打印变量类型,你会看到它。

      #case 2
      def fun2(arg2):
          
          arg2 += [4]
          
      my_var2 = [1,2,3]
      #fun(my_var2)
      print(type(my_var2))
      print(type(my_var2[0]))
      
      #case 4 where no type assigned
      def fun4(arg44):
          
          print(arg)
      
      #fun(myvar4)
      print(arg4)
      

      Watch this code in action with a visual explanation.

      【讨论】:

        【解决方案4】:

        在函数中声明的任何变量都是局部变量,但列表和字典的行为有点不同。即使您不写global list_name,也可以将元素附加到列表中 在函数内部也不将列表作为参数传递给函数。只有 list 和 dict 以这种方式运行。然而,案例 2 和案例 3 的差异似乎是一个错误。好像写的时候

        a = [1,2,3]
        def fun(a_list):
            a_list = a_list + [4]
            print(a_list)
        fun(a)
        
        >>>[1,2,3,4]
        

        你得到 [1,2,3,4],所以它成为局部变量,但是当你写 arg += [4] 时,它表现为全局变量

        【讨论】:

          猜你喜欢
          • 2011-01-21
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2020-06-12
          • 1970-01-01
          • 2011-03-26
          • 2012-03-17
          • 2011-04-21
          相关资源
          最近更新 更多