Python中设置变量作为默认值时容易遇到的错误_python

思考一下下面的代码片段:
 

def foo(numbers=[]):
  numbers.append(9)
  print numbers

在这里,我们定义了一个 list (默认为空),给它加入9并且打印出来。
 

>>> foo()
[9]
>>> foo(numbers=[1,2])
[1, 2, 9]
>>> foo(numbers=[1,2,3])
[1, 2, 3, 9]

看起来还行吧?可是当我们不输入number 参数来调用 foo 函数时,神奇的事情发生了:
 

>>> foo() # first time, like before
[9]
>>> foo() # second time
[9, 9]
>>> foo() # third time...
[9, 9, 9]
>>> foo() # WHAT IS THIS BLACK MAGIC?!
[9, 9, 9, 9]

那么,这是神马情况?直觉告诉我们无论我们不输入 number 参数调用 foo 函数多少次,这里的9应该被分配进了一个空的 list。这是错的!在Python里,函数的默认值实在函数定义的时候实例化的,而不是在调用的时候。

那么我们仍然会问,为什么在调用函数的时候这个默认值却被赋予了不同的值?因为在你每次给函数指定一个默认值的时候,Python都会存储这个值。如果在调用函数的时候重写了默认值,那么这个存储的值就不会被使用。当你不重写默认值的时候,那么Python就会让默认值引用存储的值(这个例子里的numbers)。它并不是将存储的值拷贝来为这个变量赋值。这个概念可能对初学者来说,理解起来会比较吃力,所以可以这样来理解:有两个变量,一个是内部的,一个是当前运行时的变量。现实就是我们有两个变量来用相同的值进行交互,所以一旦 numbers 的值发生变化,也会改变Python里面保存的初始值的记录。

那么解决方案如下:
 

def foo(numbers=None):
  if numbers is None:
    numbers = []
  numbers.append(9)
  print numbers

通常,当人们听到这里,大家会问另一个关于默认值的问题。思考下面的程序:
 

def foo(count=0):
  count += 1
  print count

当我们运行它的时候,其结果完全是我们期望的:
 

>>> foo()
1
>>> foo()
1
>>> foo(2)
3
>>> foo(3)
4
>>> foo()
1

这又是为啥呢?其秘密不在与默认值被赋值的时候,而是这个默认值本身。整型是一种不可变的变量。跟 list 类型不同,在函数执行的过程中,整型变量是不能被改变的。当我们执行 count+=1 这句话时,我们并没有改变 count 这个变量原有的值。而是让 count 指向了不同的值。可是,当我们执行 numbers.append(9) 的时候,我们改变了原有的 list 。因而导致了这种结果。

下面是在函数里使用默认值时会碰到的另一种相同问题:
 

def print_now(now=time.time()):
  print now

跟前面一样,time.time() 的值是可变的,那么它只会在函数定义的时候计算,所以无论调用多少次,都会返回相同的时间 — 这里输出的时间是程序被Python解释运行的时间。

>>> print_now()
1373121487.91
>>> print_now()
1373121487.91
>>> print_now()
1373121487.91

* 这个问题和它的解决方案在 Python 2.x 和 3.x 里都是类似的,在Python 3.x 里面唯一的不同,是里面的print 表达式应该是函数调用的方式(print(numbers))。

以上是小编为您精心准备的的内容,在的博客、问答、公众号、人物、课程等栏目也有的相关内容,欢迎继续使用右上角搜索按钮进行搜索python
变量
python 变量默认值、python函数参数默认值、python参数默认值、python 默认值、python dict 默认值,以便于您获取更多的相关知识。

时间: 2024-09-15 22:55:09

Python中设置变量作为默认值时容易遇到的错误_python的相关文章

Ruby中设置累加的默认值

问题描述 初学Ruby,哪位前辈可以指教一下: 我连接的postgersql数据库,要求在迁移中设置累加的默认值. 一张表employee中,字段有id,eid,aaeid是自身的一个外键,一对多的关系 条件是在相同的eid下,假如所有aa都为null,则把第一条aa修改为10,其他的aa值根据当前最大的aa值累加+10(也就是第二条为20,第三条为30...).否则,有aa为null时,也根据当前最大的值累加+10. 问题补充:jsntghf 写道 解决方案 model或控制器中都行解决方案二

Python中设置变量访问权限的方法_python

在Class内部,可以有属性和方法,而外部代码可以通过直接调用实例变量的方法来操作数据,这样,就隐藏了内部的复杂逻辑. 但是,从前面Student类的定义来看,外部代码还是可以自由地修改一个实例的name.score属性: >>> bart = Student('Bart Simpson', 98) >>> bart.score 98 >>> bart.score = 59 >>> bart.score 59 如果要让内部属性不被外部

解析Python中的变量、引用、拷贝和作用域的问题_python

在Python中,变量是没有类型的,这和以往看到的大部分编辑语言都不一样.在使用变量的时候,不需要提前声明,只需要给这个变量赋值即可.但是,当用变量的时候,必须要给这个变量赋值:如果只写一个变量,而没有赋值,那么Python认为这个变量没有定义.如下:   >>> a Traceback (most recent call last): File "<stdin>", line 1, in <module> NameError: name 'a

js设置function参数默认值

 div+css模拟js信息框的类库时遇到一个问题当没有传递参数过去时自动使用提示信息作为窗口标题,具体的实现如下 今天写一个div+css模拟js信息框的类库时遇到一个问题,我希望当我没有传递参数过去时自动使用"提示信息"作为窗口标题.我试着这样写   代码如下: function MessageBox(title=""){  }    毫无疑问我运行失败了(要不然我也不会发这博文了)    最后经过一番百度,发现了这么个好东西   代码如下: function

js设置function参数默认值(适合没有传参情况)_javascript技巧

今天写一个div+css模拟js信息框的类库时遇到一个问题,我希望当我没有传递参数过去时自动使用"提示信息"作为窗口标题.我试着这样写 复制代码 代码如下: function MessageBox(title=""){ } 毫无疑问我运行失败了(要不然我也不会发这博文了) 最后经过一番百度,发现了这么个好东西 复制代码 代码如下: function test(a){ var b=arguments[0]?arguments[0]:50; return a+':'+b

深入讨论Python函数的参数的默认值所引发的问题的原因_python

本文将介绍使用mutable对象作为Python函数参数默认值潜在的危害,以及其实现原理和设计目的陷阱重现 我们就用实际的举例来演示我们今天所要讨论的主要内容. 下面一段代码定义了一个名为 generate_new_list_with 的函数.该函数的本意是在每次调用时都新建一个包含有给定 element 值的list.而实际运行结果如下:   Python 2.7.9 (default, Dec 19 2014, 06:05:48) [GCC 4.2.1 Compatible Apple LL

ios-关于设置滚动条的默认值

问题描述 关于设置滚动条的默认值 如何在每次应用返回背景时设置滚动条的默认值? 滚动条如下: - (IBAction)slider1:(id)sender { UISlider *slider = (UISlider *)sender; //declare slider NSLog(@"%f",slider.value; } 如何设置? 解决方案 添加 observer 到 UIApplicationWillEnterForegroundNotification [[NSNotific

python中查看变量内存地址的方法

  这篇文章主要介绍了python中查看变量内存地址的方法,涉及Python中id使用技巧,需要的朋友可以参考下 本文实例讲述了python中查看变量内存地址的方法.分享给大家供大家参考.具体实现方法如下: 这里可以使用id ? 1 2 3 4 5 >>> print id.__doc__ id(object) -> integer Return the identity of an object. This is guaranteed to be unique among sim

android-Android 怎么在一个网页链接中设置变量 这个格式是怎么样的

问题描述 Android 怎么在一个网页链接中设置变量 这个格式是怎么样的 就比如http://www.wwwwwwddd.com/api/get_post?post_type=news&id=??? 在这个链接中,如何在ID=后的???中设置变量 使得在其他方法中的参数能传过去. 解决方案 String id = null; xxxx?post_type=news&id="+id; 解决方案二: xxxx?post_type=news&id=123 解决方案三: 求大神