繁体   English   中英

Python-入站出站参数

[英]Python - inbound outbound argument

我已经在《专家Python编程》中阅读了有关这种极端情况的信息。 检查此代码:

def f(arg={}):
    arg['3'] = 4
    return arg

>>> print f()
{'3': 4}
>>> res = f()
>>> res['4'] = 'Still here'
>>> print f()
{'3': 4, '4': 'Still here'}

我还不清楚为什么最后一次调用f时(保存了它的返回值之后),而不是为arg分配空dict(因为它没有参数地调用),而是保留了旧的引用。

该书这样说:“如果在参数中创建对象,则如果函数返回该对象,则参数引用仍然有效”。

我了解“这就是它的工作方式”,但是为什么会这样呢?

您的问题默认为可变参数(在这种情况下为字典):

def f(arg={}):
    arg['3'] = 4
    return arg

应该:

def f(arg=None):
    arg = arg if arg is not None else {}
    arg['3'] = 4
    return arg

产量:

>>> print f()
{'3': 4}
>>> res = f()
>>> res['4'] = 'Still here'
>>> print f()
{'3': 4}

如您所愿。

这里的问题是,默认参数是在首次定义/解析函数时进行评估的,而不是在调用它们时进行评估。 这只是您需要注意的python解析器的细微差别。

为什么,请查看“最少惊讶”和可变默认参数

因为默认参数仅被评估一次,所以在评估和创建函数时(它们是函数定义的一部分,可以通过例如inspect.getargspec进行获取)。

由于它们是函数的一部分,因此对函数的每次调用都将具有相同的默认值实例 如果它是一个不变的值,那么这不是问题,但是一旦它变得可变,它就可以成为陷阱。

给定班级定义,班级定义中也存在相同的“特征”:

class A(object):
    foo = {}

呼唤

x = A() 
y = A()
x.foo['bar'] = "baz"

...将给出y.foo ['bar']的值为“ baz”,因为x和y具有相同的 foo。 这就是为什么成员初始化应该在init而不是类主体中进行的原因。

声明函子后,默认参数将被创建一次,因此对f()的每次调用都将获得字典的相同实例,该实例开始为空。 这能回答问题吗?

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM