DC's blog DC's blog
首页
  • 计算机基础
  • linux基础
  • mysql
  • git
  • 数据结构与算法
  • axure
  • english
  • docker
  • opp
  • oop
  • 网络并发编程
  • 不基础的py基础
  • 设计模式
  • html
  • css
  • javascript
  • jquery
  • UI
  • 第一次学vue
  • 第二次学vue
  • Django
  • drf
  • drf_re
  • 温故知新
  • flask
  • 前后端不分离

    • BBS
    • 订单系统
    • CRM
  • 前后端部分分离

    • pear-admin-flask
    • pear-admin-django
  • 前后端分离

    • 供应链系统
  • 理论基础
  • py数据分析包
  • 机器学习
  • 深度学习
  • 华中科大的网课
  • cursor
  • deepseek
  • 杂文
  • 罗老师语录
  • 关于我

    • me
  • 分类
  • 归档
GitHub (opens new window)

DC

愿我一生欢喜,不为世俗所及.
首页
  • 计算机基础
  • linux基础
  • mysql
  • git
  • 数据结构与算法
  • axure
  • english
  • docker
  • opp
  • oop
  • 网络并发编程
  • 不基础的py基础
  • 设计模式
  • html
  • css
  • javascript
  • jquery
  • UI
  • 第一次学vue
  • 第二次学vue
  • Django
  • drf
  • drf_re
  • 温故知新
  • flask
  • 前后端不分离

    • BBS
    • 订单系统
    • CRM
  • 前后端部分分离

    • pear-admin-flask
    • pear-admin-django
  • 前后端分离

    • 供应链系统
  • 理论基础
  • py数据分析包
  • 机器学习
  • 深度学习
  • 华中科大的网课
  • cursor
  • deepseek
  • 杂文
  • 罗老师语录
  • 关于我

    • me
  • 分类
  • 归档
GitHub (opens new window)
  • python面向过程

  • python面向对象

  • 网络并发编程

  • 不基础的py基础

    • 默认参数
    • 装饰器
    • Code Object
  • 设计模式

  • python_Need
  • 不基础的py基础
DC
2024-06-20

默认参数


先看一个默认参数的坑:

class Player:
    def __init__(self, name, items=[]):
        self.name = name
        self.items = items
        print(id(self.items))


if __name__ == '__main__':
    p1 = Player("Alice")
    p2 = Player("Bob")
    p3 = Player("dc", ["sword"])

    p1.items.append("armor")
    p2.items.append("sword")

    print(p1.items)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

玩家 有name(姓名)和items(身上的道具). 通常情况下, 大部分玩家一开始是没有道具的 [], 只有付费玩家一开始有道具["sword"].
为了方便就在初始化函数__init__里设置了默认参数 items=[].
后来, Alice和Bob才通过努力获取到了道具, p1.items.append("armor") 、p2.items.append("sword")

乍一看, 没啥问题. 实则掉入了 默认参数的陷阱. 打印结果进行验证:

4438029888
4438029888
4437884608
['armor', 'sword']
1
2
3
4

我们只给了Alice道具 armor , 但根据打印结果,可知 他有 armor和sword. Why?

《官方文档解释》:
当函数被定义的时候,只会把这个默认参数表达式求一次值.然后每一次调用的时候,默认参数都会使用这个值.
注:当你使用一个mutable的默认参数时,一定要理解你在干什么! (大部分情况下,这么使用都是不正确的

换句话说, p1和p2 初始化的时候 用的items是同一个list / Alice和Bob share(共享) 了一个 list.
而list在python里是mutable(可变)的. 所以就出现问题啦.

print(id(self.items)) 可验证这个猜想, id()是一个 可以确认两个object是不是同一个 的方法.

那如何解决呢? 官方文档也给出了解决方案.

class Player:
    def __init__(self, name, items=None):
        self.name = name
        if items is None:
            self.items = []
        else:
            self.items = items
        print(id(self.items))


if __name__ == '__main__':
    p1 = Player("Alice")
    p2 = Player("Bob")
    p3 = Player("dc", ["sword"])

    p1.items.append("armor")
    p2.items.append("sword")

    print(p1.items)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19

看控制台打印结果, 默认参数的陷阱 解决啦!

4440774144
4440629056
4440773888
['armor']
1
2
3
4

-1- 判断None的时候, 一定要用is.   
    arg is None ; arg is not None 是可以的! arg == None 是不可以的!
-2- 自定义类型的对象可以成为字典的键吗? 大抵是有问题的.
-3- 
1
2
3
4

脚本编写
装饰器

← 脚本编写 装饰器→

最近更新
01
deepseek本地部署+知识库
02-17
02
实操-微信小程序
02-14
03
教学-cursor深度探讨
02-13
更多文章>
Theme by Vdoing | Copyright © 2023-2025 DC | One Piece
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式