我叫李明,教Python编程快十年了。每次上课讲到函数参数,教室里就安静得可怕。学生们眼神飘忽,我知道他们在想什么——参数不就是个变量吗,有什么好学的。直到他们自己写完代码跑不动,才开始后悔。
先说说最简单的位置参数。你定义一个函数def info(name, age, city),调用的时候info('张三', 25, '北京'),顺序必须一模一样。很多人觉得这没什么,结果写了好几层调用以后,不小心写成info(25, '北京', '张三')。参数多了以后眼睛都看花,谁还记得当初定义时第几个位置对应什么数据。这种错误在代码里就像定时炸弹,不知道什么时候会炸。
再说默认参数,这是踩坑的重灾区。有人写了个函数处理用户列表:def add_user(name, user_list=[])。然后调用了三次,每次只看结果都只加了一个用户,感觉没问题。等代码上线跑起来,发现所有用户都挤到同一个列表里了。原因是你觉得每次调用都会新建一个空列表,实际上默认参数只会在函数定义时创建一次。那个列表就像个公共垃圾桶,所有人都往里扔东西。
还有可变参数,args和kwargs。我见过学生写了一个求和函数:def total(nums),心里想的是传入多个数字。结果他同事调用的方式五花八门,有的传列表,有的传元组,有的混着传。最后代码维护的时候,没人知道这个函数到底该接收什么格式的数据。每个人都要去翻函数定义,看了半天也没搞明白。
最让人崩溃的是参数的互相影响。你定义了一个函数,参数里有可变对象,比如列表或字典。你在函数里改了参数的值,结果外面变量也跟着变了。有个学生写了个函数处理订单数据,本来只是想内部统计一下,不小心把原始数据给破坏了。等发现的时候,早期订单信息已经全乱套了,修复数据花了两天时间。
还有个学生,函数参数写了十几个。每个参数都有默认值,还混着位置参数和关键字参数。调用的时候,他自己都记不清哪个参数该放哪个位置。每次调用都要翻函数定义,一行行对照。后来他换了个工作,新同事接手他的代码,看了半天直接说重构吧,这代码没法维护。
写参数这事儿,核心就一句话:别指望调用者能记住你的设计。你自己写的时候思路清晰,过一个月回头看,脑子一样是空的。参数数量尽量少,超过三个就想想能不能合并成对象。默认参数尽量用不可变类型,None比空列表安全得多。调用的时候多用关键字参数,就算以后参数位置变了,代码也不容易出错。
我见过最离谱的一次,有个学生定义了一个函数,参数里有个叫data的字典,然后函数内部又建了个同名变量。他同事误以为这个参数是用来存数据的,结果传进来一个空字典,函数跑起来没报错,就是结果全错了。这种同名变量覆盖参数的情况,排查起来特别痛苦。
参数写不好,坑的是自己。等代码上了生产环境,用户开始反馈问题,你半夜爬起来查bug,翻到函数调用那行,看着一堆参数,头都大了。那个瞬间你就会明白,写参数多花十分钟,后面能省下十个小时。