• linkedu视频
  • 平面设计
  • 电脑入门
  • 操作系统
  • 办公应用
  • 电脑硬件
  • 动画设计
  • 3D设计
  • 网页设计
  • CAD设计
  • 影音处理
  • 数据库
  • 程序设计
  • 认证考试
  • 信息管理
  • 信息安全
菜单
linkedu.com
  • 网页制作
  • 数据库
  • 程序设计
  • 操作系统
  • CMS教程
  • 游戏攻略
  • 脚本语言
  • 平面设计
  • 软件教程
  • 网络安全
  • 电脑知识
  • 服务器
  • 视频教程
  • vbs
  • DOS/BAT
  • hta/htc
  • python
  • perl
  • VBA
  • ColdFusion
  • ruby
  • PowerShell
  • Lua
  • Golang
  • linux shell
您的位置:首页 > 脚本语言 >python > Python中的默认参数详解

Python中的默认参数详解

作者:junjie 字体:[增加 减小] 来源:互联网

junjie 通过本文主要向大家介绍了python开发技术详解,python os模块详解,python正则表达式详解,python 字典详解,python类详解等相关知识,希望对您有所帮助,也希望大家支持linkedu.com www.linkedu.com

文章的主题

不要使用可变对象作为函数的默认参数例如 list,dict,因为def是一个可执行语句,只有def执行的时候才会计算默认默认参数的值,所以使用默认参数会造成函数执行的时候一直在使用同一个对象,引起bug。

基本原理

在 Python 源码中,我们使用def来定义函数或者方法。在其他语言中,类似的东西往往只是一一个语法声明关键字,但def却是一个可执行的指令。Python代码执行的时候先会使用 compile 将其编译成 PyCodeObject.

PyCodeObject 本质上依然是一种静态源代码,只不过以字节码方式存储,因为它面向虚拟机。因此 Code 关注的是如何执行这些字节码,比如栈空间大小,各种常量变量符号列表,以及字节码与源码行号的对应关系等等。

PyFunctionObject 是运行期产生的。它提供一个动态环境,让 PyCodeObject 与运行环境关联起来。同时为函数调用提供一系列的上下文属性,诸如所在模块、全局名字空间、参数默认值等等。这是def语句执行的时候干的活。

PyFunctionObject 让函数面向逻辑,而不仅仅是虚拟机。PyFunctionObject 和 PyCodeObject 组合起来才是一个完整的函数。

下文翻译了一篇文章,有一些很好的例子。但是由于水平有限,有些不会翻译或者有些翻译有误,敬请谅解。如果有任何问题请发邮件到 acmerfight圈gmail.com,感激不尽

主要参考资料 书籍:《深入Python编程》 大牛:shell 和 Topsky

Python对于函数中默认参数的处理往往会给新手造成困扰(但是通常只有一次)。

当你使用“可变”的对象作为函数中作为默认参数时会往往引起问题。因为在这种情况下参数可以在不创建新对象的情况下进行修改,例如 list dict。
>>> def function(data=[]):
...     data.append(1)
...     return data
...
>>> function()
[1]
>>> function()
[1, 1]
>>> function()
[1, 1, 1]
</div>
像你所看到的那样,list变得越来越长。如果你仔细地查看这个list。你会发现list一直是同一个对象。
>>> id(function())
12516768
>>> id(function())
12516768
>>> id(function())
12516768
</div>
原因很简单: 在每次函数调用的时候,函数一直再使用同一个list对象。这么使用引起的变化,非常“sticky”。

为什么会发生这种情况?

当且仅当默认参数所在的“def”语句执行的时候,默认参数才会进行计算。请看文档描述

https://docs.python.org/2/reference/compound_stmts.html#function-definitions
其中有下面一段

"Default parameter values are evaluated when the function definition is executed. This means that the expression is evaluated once, when the function is defined, and that the same “pre-computed” value is used for each call. This is especially important to understand when a default parameter is a mutable object, such as a list or a dictionary: if the function modifies the object (e.g. by appending an item to a list), the default value is in effect modified. This is generally not what was intended. A way around this is to use None as the default, and explicitly test for it in the body of the function,e.g.:
def whats_on_the_telly(penguin=None):
    if penguin is None:
        penguin = []
    penguin.append("property of the zoo")
    return penguin
"
</div>
"def"是Python中的可执行语句,默认参数在"def"的语句环境里被计算。如果你执行了"def"语句多次,每次它都将会创建一个新的函数对象。接下来我们将看到例子。

用什么来代替?

像其他人所提到的那样,用一个占位符来替代可以修改的默认值。None
def myfunc(value=None):
    if value is None:
        value = []
    # modify value here
</div>
如果你想要处理任意类型的对象,可以使用sentinel
sentinel = object()

def myfunc(value=sentinel):
    if value is sentinel:
        value = expression
    # use/modify value here
</div>
在比较老的代码中,written before “object” was introduced,你有时会看到
sentinel = ['placeholder']
</div>
译者注:太水,真的不知道怎么翻译了。我说下我的理解 有时逻辑上可能需要传递一个None,而你的默认值可能又不是None,而且还刚好是个列表,列表不
可以写在默认值位置,所以你需要占位符,但是用None,你又不知道是不是调用者传递过来的那个

正确地使用可变参数

最后需要注意的是一些高深的Python代码经常会利用这个机制的优势;举个例子,如果在一个循环里创建一些UI上的按钮,你可能会尝试这样去做:
for i in range(10):
    def callback():
        print "clicked button", i
    UI.Button("button %s" % i, callback)
</div>
但是你却发现callback打印出相同的数字(在这个情况下很可能是9)。原因是Python的嵌套作用域只是绑定变量,而不是绑定数值的,所以callback只看到了变量i绑定的最后一个数值。为了避免这种情况,使用显示绑定。
for i in range(10):
    def callback(i=i):
        print "clicked button", i
    UI.Button("button %s" % i, callback)
</div>
i=i把callback的参数i(一个局部变量)绑定到了当前外部的i变量的数值上。(译者注:如果不理解这个例子,请看http://stackoverflow.com/questions/233673/lexical-closures-in-python)

另外的两个用途local caches/memoization
def calculate(a, b, c, memo={}):
    try:
        value = memo[a, b, c] # return already calculated value
    except KeyError:
        value = heavy_calculation(a, b, c)

您可能想查找下面的文章:

  • python中OrderedDict的使用方法详解
  • Python中异常重试的解决方案详解
  • 详解python 字符串和日期之间转换 StringAndDate
  • Python 操作MySQL详解及实例
  • python中OrderedDict的使用方法详解
  • Python中异常重试的解决方案详解
  • 详解python 字符串和日期之间转换 StringAndDate
  • Python 操作MySQL详解及实例
  • Python 登录网站详解及实例
  • 详解Python中类的定义与使用

相关文章

  • python搭建简易服务器分析与实现
  • Ruby元编程基础学习笔记整理
  • 跟老齐学Python之画圈还不简单吗?
  • Flask框架的学习指南之开发环境搭建
  • Python中用altzone()方法处理时区的教程
  • python解析模块(ConfigParser)使用方法
  • Python读取Excel的方法实例分析
  • Python实现统计单词出现的个数
  • python模拟鼠标拖动操作的方法
  • python迭代器与生成器详解

文章分类

  • vbs
  • DOS/BAT
  • hta/htc
  • python
  • perl
  • VBA
  • ColdFusion
  • ruby
  • PowerShell
  • Lua
  • Golang
  • linux shell

最近更新的内容

    • Python的一些用法分享
    • python实现linux下使用xcopy的方法
    • Using Django with GAE Python 后台抓取多个网站的页面全文
    • Python的高级Git库 Gittle
    • 浅谈Python单向链表的实现
    • 通过实例浅析Python对比C语言的编程思想差异
    • Python中列表、字典、元组数据结构的简单学习笔记
    • 深入解析Python中的上下文管理器
    • 全面解析Python的While循环语句的使用方法
    • 简单介绍Python中的decode()方法的使用

关于我们 - 联系我们 - 免责声明 - 网站地图

©2020-2025 All Rights Reserved. linkedu.com 版权所有