参考链接: Python函数中的默认参数

详细介绍Python函数中的默认参数

import datetime as dt

def log_time(message, time=None):

if time is None:

time=dt.datetime.now()

print("{0}: {1}".format(time.isoformat(), message))

最近我在一段Python代码中发现了一个因为错误的使用默认参数而产生的非常恶心的bug。如果您已经知道关于默认参数的全部内容了,只是想嘲笑一下我这可笑的错误,请直接跳到本文末尾。哎,这段代码是我写的,但是我非常确定那天我被恶魔附体了。你懂的,有时候就是这样。

本文仅仅是总结一下关于Python函数的标准参数和默认参数的一些基本内容。提醒你注意你的代码中可能存在的陷阱。如果你刚开始接触Python,开始写一些函数,我真心推荐你看一下Python官方手册中关于函数的内容,链接如下:Defining Functions 以及 More on Defining Functions。 简单复习一下函数

Python是一个强大的面向对象语言,它把这种编程范式推向了顶峰。但是,面向对象编程仍然需要依靠函数这一概念,你可以用它来处理数据。Python对于可调用对象有一个更宽泛的概念,即任何对象都可以被调用,调用的意思是对其应用数据。

函数在Python中是可调用对象,并且乍一看,它和其他语言中的函数有着类似的行为。它们获取一些数据,这些数据被称为参数,然后处理它们,接着返回结果(如果没有return语句则是None)

参数被声明为占位符(在定义函数的时候),用以代表那些当函数调用时被实际传入的对象。在Python中你不需要声明参数的类型(例如,像你在C或Java中做的那样)因为Python哲学依赖于多态。

记住,Python的变量是引用,即实际变量的内存地址。这意味着Python的函数永远以“传址”的方式工作(这里使用了一个C/C++术语),当你调用一个函数的时候,并不是复制了一份参数的值来替换占位符,而是把占位符指向了变量本身。这导致了一个非常重要的结果:你可以在函数内部改变这个变量的值。这里有一个很好可视化讲解,关于引用机制。

引用在Python扮演着非常重要的角色,它是Python完全多态方式的骨干。关于这个非常重要的主题,请点击这个链接 查看更好的解释。

为了检查你是否理解了这门语言的这一基本特性,请跟随这段简单的代码(变量ph代表的是“占位符(placeholder)”)

>>> def print_id(ph):

... print(hex(id(ph)))

...

>>> a = 5

>>> print(hex(id(a)))

0x84ab460

>>> print_id(a)

0x84ab460

>>>

>>> def alter_value(ph):

... ph = ph + 1

... return ph

...

>>> b = alter_value(a)

>>> b

6

>>> a

5

>>> hex(id(a))

'0x84ab460'

>>> hex(id(b))

'0x84ab470'

>>>

>>> def alter_value(ph):

... ph.append(1)

... return ph

...

>>> a = [1,2,3]

>>> b = alter_value(a)

>>> a

[1, 2, 3, 1]

>>> b

[1, 2, 3, 1]

>>> hex(id(a))

'0xb701f72c'

>>> hex(id(b))

'0xb701f72c'

>>>

如果你对这里发生的事情并不感到吃惊,那说明你已经掌握了Python中最为重要的部分之一,你可以放心的跳过下面的解释了。

print_id()函数显示,函数内部的占位符同运行时传入的变量完全一样(它们的内存地址一致)。

两个版本的alter_value()意在改变传入参数的值。正如你所看到的,第一个alter_value() 并没有像第二个alter_value()一样成功的改变变量a的值。这是为什么呢?实际上两者的行为是一样的,都是尝试修改传入的原始变量的值,但是在Python中,有些变量是不可变的(immutable),整数就在此列。另一方面,列表并不是不可变的,所以函数得以完成它的名字所保证的工作。 关于Python中的函数,还有一些要说的,但是这些是关于标准的参数的基本知识。 默认参数值

有时候你需要定义一个函数,让它接受一个参数,而且在这个参数出现或不出现时,函数有不同的行为。如果一门语言不支持这种情况,你就只有两个选择:第一种是定义两个不同的函数,决定每次调用应该选择调用哪个,第二种是 两种方法都是可行的,但是都不是最佳的。

Python和其他语言一样,支持默认参数值,即函数参数可以是调用时指定的,也可以留空,自动接受一个预定义的值。

一个关于默认值的非常简单(也很没用)的例子如下:

def log(message=None):

if message:

print("LOG: {0}".format(message))

这个函数可以带一个参数运行(可以是None)

>>> log("File closed")

LOG: File closed

>>> log(None)

>>>

但是同样也可以不带参数运行,这种情况下它会接受一个函数原型中设置的默认值(本例中是None)

>>> log()

>>>

你可以在标准库中找到更多有趣的例子,比如在open()函数中

open(file, mode='r', buffering=-1, encoding=None, errors=None, newline=None, closefd=True, opener=None)

函数原型可以证明,例如 f = open(’/etc/hosts’)这样的调用,通过传入默认值隐藏了很多参数 (mode, buffering, encoding, 等),并且使这个函数的典型应用案例变得非常简单易用。

正如你在内建的open()函数中看到的那样,我们可以在函数中使用标准或者默认参数,但是两者在函数中出现的次序是固定的:首先调用标准参数,然后调用默认参数。

def a_rich_function(a, b, c, d=None, e=0):

pass

原因是显而易见的:如果我们可以在标准参数前面放置一个默认参数,语言就无法理解,默认参数是否已经被初始化。例如,考虑下面这个函数定义

def a_rich_function(a, b, d=None, c, e=0):

pass

当调用函数a_rich_function(1, 2, 4, 5)时,我们传入了什么参数? 是d=4, c=5 还是c=4, e=5?因为d有一个默认的值。因此这种顺序的定义是被禁止的,如果你这样做,Python会抛出一个SyntaxError

>>> def a_rich_function(a, b, d=None, c, e=0):

... pass

...

File "<stdin>", line 1

SyntaxError: non-default argument follows default argument

>>>

默认参数求值

默认参数可以通过普通值或是函数调用结果来提高,但是后者这种技术需要一个特别的警示

一个普通的值是硬编码的,因此除了编译时,其他时候是不需要求值的,但是函数调用期望在运行时执行求值。所以我们可以这样写

import datetime as dt

def log_time(message, time=dt.datetime.now()):

print("{0}: {1}".format(time.isoformat(), message))

每次我们调用log_time()时都期望它能够正确提供当前时间。悲剧的是并没有成功:默认参数在定义时求值(比如说当你首次导入模块时),调用的结果如下 如果把默认值赋给一个类的实例,结果会更加奇怪,根据。。通常的解决方法是把默认参数替换为None,并且在函数内部检查参数值。

写到这里,给大家推荐一个资源很全的python学习聚集地,点击进入,这里有资深程序员分享以前学习心得,学习笔记,还有一线企业的工作经验,且给大家精心整理一份python零基础到项目实战的资料,每天给大家讲解python最新的技术,前景,学习需要留言的小细节 结论

默认参数能够极大的简化API,你需要关注它唯一的“失败点”,即求值的时机。令人惊奇的是,Python最基本的内容之一,函数的参数和引用,是最大的错误源之一,有时候对于有经验的程序员也一样。我建议抽时间学习一下引用和多态。

[转载] 详细介绍Python函数中的默认参数相关推荐

  1. 站长在线Python精讲:在Python函数中的默认参数详解

    欢迎你来到站长在线的站长学堂学习Python知识,本文学习的是<在Python函数中的默认参数详解>.本文的主要内容有:默认参数的概念和默认参数的示例.默认参数不能设置可变对象. 目录 1 ...

  2. 站长在线Python教程精讲:在Python函数中的关键字参数详解

    欢迎你来到站长在线的站长学堂学习Python知识,本文学习的是<在Python函数中的关键字参数详解>.本文的主要内容有:关键字参数的含义和关键字参数的应用举例. 目录 1.关键字参数的含 ...

  3. python位运算符_详细介绍Python语言中的按位运算符

    按位运算符是把数字看作二进制来进行计算的.Python中的按位运算法则如下: 按位与 ( bitwise and of x and y ) & 举例: 5&3 = 1 解释: 101 ...

  4. python语言中运算符号_详细介绍Python语言中的按位运算符

    <从问题到程序:用Python学编程和计算>--2.11 补充材料 本节书摘来自华章计算机<从问题到程序:用Python学编程和计算>一书中的第2章,第2.11节,作者:裘宗燕 ...

  5. python:函数中五花八门的参数形式(茴香豆的『回』字有四种写法)

    毫不夸张的说,python语言中关于函数参数的使用,是我见过最为灵活的,随便怎么玩都可以,本文以数学乘法为例,演示几种不同的传参形式: 一.默认参数 def multiply1(x, y):retur ...

  6. python函数之可变默认参数

    文章目录 问题剖析 元组的使用 一个 Python Bug 干倒了估值 1.6 亿美元的公司 今天在CSDN首页看到这篇文章,不仅感概: 水能载舟,亦能覆舟 作为一家仰仗技术出身的公司,最终却因为技术 ...

  7. Python函数中4种参数的使用

    1.必需的参数: 必须参数须以正确的顺序传入函数,调用的数量必须和声明时的一样 def f(name,age):print('I am %s,I am %d'%(name,age))f('alex', ...

  8. 用类来实现输入输出时间,定义多个类对象分别输入输出各对象的时间(时:分:秒),使用函数,数据成员不再由键盘输入,而在调用函数时由实参给出,并在函数中使用默认参数

    //个人留着复习用 #include using namespace std; class Time {public: int hour; //类 int minute; int sec; }; in ...

  9. 详细介绍js函数中的arguments

    arguments相当于一个"伪数组" ECMAScript函数的参数和其他的语言还是有些不同的,他并不介意你传进来多少个参数,以及参数的数据类型:通俗的说,即使你在定义函数时,只 ...

最新文章

  1. 一个老工程师对理工科学生的忠告
  2. ECMAScript arguments 对象(摘自W3C)
  3. 显示外部页面_前端设计-响应式页面开发基础
  4. Spring和JSF集成:转换器
  5. gen_fsm之门禁管理
  6. 作者:李晓明,男,北京大学教授、博士生导师。
  7. c++ double 只输出五位_C/C++编程笔记:C语言入门知识点(一),请收藏C语言最全笔记...
  8. 正则表达式之量词(重复出现)?、*、+
  9. JSP 文件上传下载系列之二[Commons fileUpload]
  10. 在Windows上安装jupyter notebook的scala kernel —— jupyter-scala
  11. BigDecimal 使用浅析
  12. labuladong算法小结
  13. 优化 RTD 温度传感系统:接线配置
  14. 2014522420145238 《信息安全系统设计基础》 第三次实验
  15. app下载统计 php,如何统计app在各个渠道的下载量?
  16. apicloud影视解析APP源码 HTML
  17. 每日力扣——95. 提莫攻击
  18. 《深入浅出MFC》观后有感
  19. 「Luogu2495」 [SDOI2011]消耗战 虚树
  20. 用C实现模拟cf(穿越火线)抽奖

热门文章

  1. 【网络流24题】【LOJ6013】负载平衡(环形纸牌均分,最小费最大流)
  2. html 悬浮在固定位置,纯CSS实现DIV悬浮(固定位置)
  3. termux使用无图形界面linux,在termux上使用图形化
  4. Coprime Sequence
  5. jquery赋值节点
  6. c++ memset 语言_C/C++ 中memset() 函数详解及其作用介绍
  7. bzoj 2707: [SDOI2012]走迷宫(Trajan+高斯消元+Dp)
  8. bzoj 1655: [Usaco2006 Jan] Dollar Dayz 奶牛商店(高精度完全背包)
  9. 设置mybb论坛后台显示为中文
  10. jQuery Mobile中主题theme样式a-z