前言

pass

正文

在 https://docs.python.org/3/tutorial/controlflow.html#default-argument-values 中,有这样一段话

Important warning: The default value is evaluated only once. This makes a difference when the default is a mutable object such as a list, dictionary, or instances of most classes. For example, the following function accumulates the arguments passed to it on subsequent calls:

大致意思为

重要警告:默认值仅计算一次。 当默认值是可变对象(例如列表,字典或大多数类的实例)时,这会有所不同。 例如,以下函数累积在后续调用中传递给它的参数:

下面给出了一个例子

def f(a, L=[]):
L.append(a)
return L print(f(1))
print(f(2))
print(f(3))

打印出来的结果是

[1]
[1, 2]
[1, 2, 3]

这是因为, 作为默认参数, python在启动时就会将变量 L 建立, 我们在函数 f 内对 L 处理就会导致后来调用的 L 已经是修改过的 L 了, 我们可以通过打印 L 的内存地址来验证

def f(a, L=[]):
print(id(L))
L.append(a)
print(id(L))
return L print(f(1))
print(f(2))
print(f(3))

结果是

4513289600
4513289600
[1]
4513289600
4513289600
[1, 2]
4513289600
4513289600
[1, 2, 3]

当然, python的文档中也给出了一个推荐的方法

If you don’t want the default to be shared between subsequent calls, you can write the function like this instead:

def f(a, L=None):
if L is None:
L = []
L.append(a)
return L

即: 将 L 默认为 None, 当该参数未传时, 将 L 设置为空列表, 在Python启动时 L 会设置为 None, 而当我们调用而不传参数 L 时, 在函数 f 内部重新给 L 赋值, 此时 L 为函数 f 内的一个私有变量, 其不会影响到参数 L 本身, 同样的我们可以通过打印内存地址来验证

def f(a, L=None):
print(id(L))
if L is None:
L = []
print(id(L))
L.append(a)
return L print(f(1))
print(f(2))
print(f(3))

输出

4467395776
4469232960
[1]
4467395776
4469232960
[2]
4467395776
4469232960
[3]

当然我们也可以在不更改函数 f 的情况下, 在每次调用 f 的时候都传输参数 L, 如果想让他为一个空列表那就传一个空列表同样能解决问题, 因为你每次指定了值, 便会在传入时修改 L 的值

def f(a, L=[]):
print(id(L))
L.append(a)
print(id(L))
return L print(f(1, []))
print(f(2, []))
print(f(3, []))

输出

4474168192
4474168192
[1]
4474168192
4474168192
[2]
4474168192
4474168192
[3]

python的默认参数的一个坑的更多相关文章

  1. 在python函数中默认参数的一些坑

    一.默认参数 python为了简化函数的调用,提供了默认参数机制: 这样在调用pow函数时,就可以省略最后一个参数不写: 在定义有默认参数的函数时,需要注意以下: 必选参数必须在前面,默认参数在后: ...

  2. 【转】Python函数默认参数陷阱

    [转]Python函数默认参数陷阱 阅读目录 可变对象与不可变对象 函数默认参数陷阱 默认参数原理 避免 修饰器方法 扩展 参考 请看如下一段程序: def extend_list(v, li=[]) ...

  3. python函数默认参数坑

    def add(a=3,b): print a,b add(4) 这样写的话,运行的话就会报错:SyntaxError: non-default argument follows default ar ...

  4. python函数参数中带有默认参数list的坑

    在python中函数参数中如果带有默认参数list遇到问题 先看一段代码 def f(x,l=[]): for i in range(x): l.append(i*i) print(l) print( ...

  5. 使用可变对象作为python函数默认参数引发的问题

    写python的都知道,python函数或者方法可以使用默认参数,比如 1 def foo(arg=None): 2 print(arg) 3 4 foo() 5 6 foo("hello ...

  6. python函数默认参数陷阱

    对于学习python的人都有这样的困惑 def foo(a=[]): a.append(5) return a Python新手希望这个函数总是返回一个只包含一个元素的列表:[5].结果却非常不同,而 ...

  7. Python面试题目之Python函数默认参数陷阱

    请看如下一段程序: def extend_list(v, li=[]): li.append(v) return li list1 = extend_list(10) list2 = extend_l ...

  8. 关于Inception默认配置的一个坑

    本文地址:https://www.cnblogs.com/ajiangg/p/9850902.html 约半年前上线了去哪儿的开源审核工具Inception(最近发现已经闭源了.....)以及基于In ...

  9. python函数默认参数为可变对象的理解

    1.代码在执行的过程中,遇到函数定义,初始化函数生成存储函数名,默认参数初识值,函数地址的函数对象. 2.代码执行不在初始化函数,而是直接执行函数体. 代码实例 这要从函数的特性说起,在 Python ...

随机推荐

  1. 《Eroico》关卡与操作设计

    操作设计: 没有给明操作教程,操作全靠蒙,只有改建的位置可以看到. 但游戏的难度并没有给玩家适应操作感,随着难度提升怪物血量增厚,但怪物并没有僵直英雄却有僵直.第一个小猫妖便给了玩家一个痛击. 方向键 ...

  2. 【Alpha冲刺阶段】Scrum Meeting Daily3

    [Alpha冲刺阶段]Scrum Meeting Daily3 1.会议简述 会议开展时间 2020/5/24 8:00-8:15 PM 会议基本内容摘要 每日汇报 个人进度.遇到的困难.明日的计划. ...

  3. hashmap底层:jdk1.8前后的改变

    将hashmap和currenthashmap放一块进行比较,是因为二者的结构相差不多,只不过后者是线程安全的. 首先说hashmap,在jdk1.8之前,hashmap的存储结构是数组+链表的形式, ...

  4. MVC部署出现403.14问题记录

    1.问题截图 2.解决办法有几种 1)在system.webServer下增加,这种是不推荐的. <modules runAllManagedModulesForAllRequests=&quo ...

  5. JavaScript:记录一些字符串和数组常用的方法

    字符串: 字符串的方法:注意:都不会改变原来的字符串,返回值为新的字符串.如果(1,2),一般是包含小标1,不包含下标2 str.charAt(i): 取str的第i+1个字符,类似数组的arr[i] ...

  6. celery定时执行任务 的使用

    1 参照博客 https://www.cnblogs.com/xiaonq/p/9303941.html#i1 1 创建celery_pro包   # 可在任意文件下 2 在 celery_pro 下 ...

  7. sql 语句使用和转换json数据

    1 连接mysql import pymysql import concurrent coon=pymysql.connect(host='localhost',user='root',passwor ...

  8. maven下载和配置

    maven就是管理架包(jar)的一个工具类,是一个绝佳的构建工具 但是maven是需要下载和配置环境的,和jdk差不多 1.首先进入apache的官网 http://maven.apache.org ...

  9. Graphql Tutorials(Episode 01)

    1.前言 最近认识到Graphql,它是一个基于DSL的api.我曾接触过一个pos机刷卡系统,它是基于JSON-DSL语言开发的框架,很有趣.可是后来,没有机会深入研究.直到最近我认识了Graphq ...

  10. ElasticSearch中head插件的简单用法

    1.首先在左侧打开Query栏. 2.Query下方的第一栏是分别输入es的地址.端口号.index.type. 3.Query下方的第二栏是输入将要执行的方式,旁边的下拉框是辅助选择执行的类型,如图 ...