【问题标题】:how python interpreter treats the position of the function definition having default parameterpython解释器如何处理具有默认参数的函数定义的位置
【发布时间】:2020-05-17 18:21:57
【问题描述】:

为什么第一个代码输出 51第二个代码输出 21。我理解第二个代码应该输出 21,但是按照我的理解,第一个代码也应该输出 21(b 的值变为 20,然后调用函数 f)。我错过了什么?

b = 50

def f(a, b=b):
    return a + b

b = 20
print(f(1))

输出:51

b = 50
b = 20

def f(a, b=b):
    return a + b
print(f(1))

输出:21

编辑:这与How to change default value of optional function parameter in Python 2.7?不同,因为这里讨论的是默认参数发生的无意更改,而不是如何有意更改默认参数的值,即这里的问题集中在python解释器如何处理位置具有默认参数的函数的函数定义。

【问题讨论】:

    标签: python python-3.x


    【解决方案1】:

    python 初学者提示:如果您使用 IDE,例如 pycharm - 您可以放置​​一个调试器并查看变量发生了什么。

    我们可以使用id(b) 更好地了解正在发生的事情,它可以让我们获得特定对象在内存中的地址:

    返回对象的“身份”。这是一个整数,它是 保证在此对象期间是唯一且恒定的 寿命。具有不重叠生命周期的两个对象可能具有相同的生命周期 id() 值。

    CPython 实现细节: 这是对象的地址 记忆。

    让我将您的代码修改为以下内容:

    b = 50
    print("b=50 :", id(b))
    
    
    def f(a, b=b):
        print("b in the function f :", id(b))
        print(id(b))
        return a + b
    
    
    b = 20
    print("b=20 :", id(b))
    print(f(1))
    

    输出如下:

    b=50 : 4528710960
    b=20 : 4528710000
    b in the function f : 4528710960
    4528710960
    51
    

    如您所见,函数内部的bb=50 具有相同的地址。

    当您执行b=20 时,创建了一个新对象。

    在 Python 中,(几乎)一切都是对象。我们通常在 Python 中称为“变量”的东西更恰当地称为名称。同样,“赋值”实际上是将名称绑定到对象。 每个绑定都有一个定义其可见性的范围,通常是名称所在的块。

    在python中

    当你这样做时

    b=50一个bindingb到一个int对象被创建在块的范围

    当我们稍后说b=20 时,int 对象b=50 不受影响。这两者本质上是两个不同的对象。

    您可以在这些链接中了解更多信息。

    【讨论】:

    • 另外,在 python 中,默认参数只计算一次(即在函数定义时)。 Python 作为一种解释性语言逐行运行。因此,在第一种情况下,def f(a, b=b) 中的内部b 将被“分配”并在该行引用外部b 的值(即50)。同样,在第二种情况下,函数中的内部b 将在该行(即20)处分配一个外部b 的值
    【解决方案2】:

    想想解释器是如何处理这个问题的。在第一种情况下,def f(a, b=b) 被解释为def f(a, b=50),因为当前作用域中b 的值是50。因此,f(1)a 分配给 1,因此,a + b = 1 + 50 = 51

    同理,在第二种情况下,函数声明时b在当前作用域内的值是20,所以定义解释为def f(a, b=20)。因此,f(1) = 21

    【讨论】:

      【解决方案3】:

      函数的不同放置导致不同错误的原因也是因为值'b'的放置。

      由于函数“f”使用命名参数“b”,因此它将变量“b”的第一次赋值作为函数“f”的参数/参数

      例如,

      b = 50
      
      def f(a, b=b):
          return a + b
      
      b = 20
      print(f(1))
      

      正如您所指出的,这会导致输出 51

      但如果我将代码更改为

      def f(a, b=b):
          return a + b
      b = 50
      b = 20
      print(f(1))
      

      这将导致以下错误:

      def f(a, b=b):
      NameError: name 'b' is not defined
      

      因此,我们可以推断出作为函数命名参数的变量的放置导致了输出的差异。

      您也可以使用全局变量

      【讨论】:

        【解决方案4】:

        因为当您在案例 1 中定义函数 f 时,您正在将 b 的值(当时是 50)分配给函数的第二个参数。

        而在情况 2 中,在将 b 的值分配给 f 的第二个参数时,它是 20

        这就是两种情况下答案不同的原因。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2016-09-27
          • 1970-01-01
          • 2013-08-11
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多