跳转至内容
  • 版块
  • 标签
  • 热门
  • 用户
  • 群组
皮肤
  • Light
  • Cerulean
  • Cosmo
  • Flatly
  • Journal
  • Litera
  • Lumen
  • Lux
  • Materia
  • Minty
  • Morph
  • Pulse
  • Sandstone
  • Simplex
  • Sketchy
  • Spacelab
  • United
  • Yeti
  • Zephyr
  • Dark
  • Cyborg
  • Darkly
  • Quartz
  • Slate
  • Solar
  • Superhero
  • Vapor

  • 默认(Flatly)
  • 不使用皮肤
折叠

Odoo 中文社区

  1. 主页
  2. 版块
  3. Python 开发
  4. 不可变动的默认值(Unmutable defaults)

不可变动的默认值(Unmutable defaults)

已定时 已固定 已锁定 已移动 Python 开发
3 帖子 2 发布者 7.9k 浏览
  • 从旧到新
  • 从新到旧
  • 最多赞同
登录后回复
此主题已被删除。只有拥有主题管理权限的用户可以查看。
  • digitalsatoriD 离线
    digitalsatoriD 离线
    digitalsatori 管理员
    写于 最后由 编辑
    #1

    在官方的邮件列表中看到以下这个话题:
    [quote]Dear community,
    It seems we have all made a quite common mistake in our python code - using empty lists or dictionaries as default values for functions.
    As it turns out, we should not have done that because that makes the defaults mutable, which may provoke strange bugs, very hard to reproduce.
    So please allow me to ask you all to change the code you contributed to the "community" and/or "extra-addons" branches. For example we should now change this
    def foo(...., context={},....):
    ....
    to this :
    def foo(...., context=None,....):
    # you should add this test only if the context is actually used
    if context is None:
    context={}
    ....

    I humbly suggest you fix the trunk branch in priority, and fix the 5.0 branches only if you feel totally comfortable with the changes.
    Please read https://bugs.launchpad.net/openobject-server/+bug/525808 for more detail.

    Lionel, for Numérigraphe SARL[/quote]

    他的大意是说在OE的开发中大量存在着一种对有默认值的参数的误用,如果不加以规范的话,会导致很多不可预测的错误,它建议将:[code]def foo(..., context={},...):
    ...
    [/code]转换为:[code]def foo(..., context=None, ...):
    if context = None:
    context = {}
    ...[/code]可是为什么这么麻烦从第一种看起来很简单的形式转变到这第二种颇啰嗦的形式呢,第一种形式会带来什么问题呢?

    在Python的函数定义中有两种形式的参数,一种是普通的形参,另一种是带默认值的形参。对于第一种形参,调用函数时必须提供对应的实参,而对于第二种形参,调用函数时如果没有提供对应的实参则会使用函数定义中该形参的默认值。所以第二种参数也称为[b]可选参数[/b]。
    这里需要强调的是,可选参数的默认值是在函数定义阶段计算确认的。函数调用时若没有提供相应的实参就会对这个默认值对象进行操作,当这个默认值是一个[b]可变对象[/b](mutable object)的话,事情就会变得有些微妙:[code]def f(x, y=[]):
    y.append(x)
    return y

    print f(10) #显示 [10]
    print f(11) #显示 [10, 11][/code]我们这里定义了一个简单的函数f,其中y是其一个可选参数,其默认值对应一个空的列表(列表作为一个容器是可变对象)。当我们用f(10)调用f函数时得到了[10]这个结果,当我们再次调用f函数f(11)时,记得我们还是在使用y所对应的这个列表对象而其成员对象已经包括了第一次运算的结果10了,所以第二次调用的结果就会是[10,11]。

    这往往并不是我们所期望的,也是带来不可预测问题的根源,所以我们将代码改成:[code]def f(x, y=None):
    if y is None: y = []
    y.append(x)
    return y
    print y(10) #显示 [10]
    print y(11) #显示 [11][/code]朋友们在代码开发时,请注意这方面的问题。

    [[i] 本帖最后由 digitalsatori 于 2010-3-14 23:05 编辑 [/i]]

    【上海先安科技】(tony AT openerp.cn)

    1 条回复 最后回复
    0
    • wjfonhandW 离线
      wjfonhandW 离线
      wjfonhand
      写于 最后由 编辑
      #2

      解释很精到,帮顶一下。

      GoodERP -- Odoo China fork

      1 条回复 最后回复
      0

      • 登录

      • 没有帐号? 注册

      • 登录或注册以进行搜索。
      • 第一个帖子
        最后一个帖子
      0
      • 版块
      • 标签
      • 热门
      • 用户
      • 群组