Python 具有默认参数的函数出现问题

Python 具有默认参数的函数出现问题,python,function,default-parameters,Python,Function,Default Parameters,我对具有默认参数的函数有一些疑问。 输出:(当然,一些数字取决于randint返回的值。) 参考文献数量:3 定义参数:([1,2,3],) 322 1119 740 ([1,2,33211118739],) 参考文献数量:3 303 参考文献数量:2 Def参数:([1,2,3,321,1118,739,302],) 303 Def参数:([1,2,3,321,1118,739,302],) 303 下面的代码给出的数字比前面的代码少,因为b和my_列表不再引用到同一地址 pri

我对具有默认参数的函数有一些疑问。


输出:(当然,一些数字取决于randint返回的值。)

参考文献数量:3
定义参数:([1,2,3],)
322
1119
740
([1,2,33211118739],)
参考文献数量:3
303
参考文献数量:2
Def参数:([1,2,3,321,1118,739,302],)
303
Def参数:([1,2,3,321,1118,739,302],)
303


下面的代码给出的数字比前面的代码少,因为b和my_列表不再引用到同一地址

print "#ref:", sys.getrefcount(my_list) # Less than previous
现在,我们有一种方法(唯一的方法?)来达到b,函数的默认参数:

Veli.func_defaults[0]

对不起,我解释得太长了。以下是我的问题:

  • 这是个问题吗?我的模块的字典压碎了我的列表变量,现在我的列表变量比以前有默认地址。然后,在函数体中使用名为my_list的全局变量的函数正在更改(增长),而我的默认参数没有更改。当执行
    a+b[-1]
    表达式时,为什么不能
    b
    查看名为
    my_list
    的全局变量?我知道,
    b
    现在与我的_列表有不同的地址(因为),但是为什么Python的实现使得
    b
    在b是函数参数时看不到全局变量?你能全面地解释一下吗

  • 使用Veli.func_默认值[0]是否有任何方法可以获得相同的结果?执行这段代码后,我想更改名为Veli的函数的默认参数。我不能用我的_列表来做这件事,因为我的_列表和b有不同的地址。一种方法是更改列表的元素,Veli.func_默认值[0]。有什么不同的方法吗

  • (与上面的代码无关)如何获取变量的地址?例如,如何获取
    b
    的地址?我使用内置函数,比如
    \uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu


  • 注:

    a) 无论出于什么原因,这些代码都可能是无用的,但我想了解一些意见。
    b) linux2上的Python 2.6.6(r266:842921010年9月15日,15:52:39)
    [GCC 4.4.5]

  • 默认参数是函数定义时的边界。行
    def Veli(a,b=my_list):
    将当时引用的对象
    my_list
    的引用放入
    func_defaults
    中。Python从不使用按引用传递-变量保存引用,这些引用总是按值传递。因此,实际上保存在
    b
    中的引用(指针)被复制,没有人记得它来自何处,也没有人费心更新它
  • 不太清楚你在问什么,请澄清<如果没有传递第二个参数,则code>b将是
    Veli.func\u默认值[0]
    ,但如果传递第二个参数,则会明显不同(当然,除非调用方访问
    func\u默认值
    …您应该假设他没有)。您可以,正如另一个答案中所建议的,将
    b
    设为默认值
    None
    ,如果
    b为None,则使用全局
    my_列表
    ——这将在每次通话中为您提供其参考的最新副本。也许您应该编写一个类,并将默认值保留为
    self
    的属性,并应用通常的
    (…=None):如果。。。无:use=default
    idiom
  • 内置函数
    id
    。实际上,它的实现定义了它返回的内容(不必是地址),只要它是一个表示对象标识的整数,即不同的对象(具有重叠的生存期)具有不同的
    id
    ,并且相同的对象在其生存期内始终提供相同的
    id
    。CPython选择的easy返回值是地址
  • 我建议你看一下,因为你的问题本质上与同一个问题有关(尽管在这个话题上的观点略有不同)

    正如您所注意到的,在执行函数定义时,
    b
    绑定到指向
    my_list
    。稍后更改
    my_list
    以指向其他对象时,
    b
    保持不变

    要获得“惰性绑定”,您需要这样编写函数:

    def Veli(a, b=None):
        if b is None:
            b = my_list # Gets value of my_list at call time
        my_list.append(randint(1,1500))
        print a + b[-1]
    

    @ncoghlan:这是一次重要的演讲,但由于OP利用了这种行为,在这里并不完全相关。哎呀,我真的以为我在重读OP的问题后删除了它……你的解释比delnan更清楚,但你只回答了一个问题,而且delnan是第一个回答者。我选了他/她。谢谢你的回答
    def Veli(a, b=None):
        if b is None:
            b = my_list # Gets value of my_list at call time
        my_list.append(randint(1,1500))
        print a + b[-1]