第一个月写Python的时候,我对着屏幕发呆。IDE没有报错,变量名挺顺眼,代码跑起来也没有异常。但我就是觉得哪里不对劲。后来同事看了一眼我的代码,说你为啥要给每个变量都写类型注释?我说这样安全。他笑了,Python不关心这个。
我写Java写了六年。习惯了在IDE里看到红色波浪线,习惯了编译时发现类型不匹配。转到Python的第一周,我写了个函数接收用户列表。传进去的可能是字符串,也可能是字典。程序没报错,但结果全错了。我花了三个小时调试。后来发现是调用方传错了参数类型。这种问题在Java里根本不会发生。
动态类型不是偷懒,是信任。但这种信任很难建立。我刚开始写的每个Python函数都带isinstance检查。同事说你这样写不如回去写Java。他说得对,我的代码看起来像Java穿了件Python的外衣。
某天下午我改了一个web服务的接口。原来的函数返回字符串,我改成了返回列表。改动地方挺多,但没有编译检查。我自信地提交了代码。上线后日志里全是AttributeError。调用方还在当字符串处理。我赶紧回滚。那个晚上我在想,静态类型帮我挡住了多少低级错误。
后来我学会了写测试。不是那种官方文档里的测试,是真正覆盖边界情况的测试。空列表传进去会怎样,None传进去会怎样,字典传进去会怎样。我在测试里把各种类型都跑一遍。这样做确实费时间,但比上线出问题强。
Python的类型提示对我帮助很大。不是强制检查,是给人看的。别人看我的代码就知道参数该传什么。我写了个装饰器做运行时校验,传错类型就抛异常。这样既保留了动态的灵活,又加了一点安全感。
有次重构一个爬虫项目。原来的代码把数据都放在字典里。字段名是字符串,值可能是数字字符串列表。我改成了类定义,给每个属性写了类型。同事说这样太复杂。我说这样安全。后来加了新需求,要解析另一种格式的页面。用类的方案只需要改一个地方。字典的方案要在五个模块里改。那一刻我突然觉得,类型不是语言的限制,是设计的选择。
一个月后我不再纠结类型了。我学会了写类型提示但不依赖它。我学会了写测试找出类型问题。我学会了用动态类型的灵活解决复杂问题。比如写一个缓存函数,可以缓存任何类型的结果。如果是Java我要写泛型,写一堆类型参数。Python里一个装饰器就够了。
现在回头看,被类型逼疯的那个月是我进步最快的时候。我学会了信任自己的代码,也学会了通过测试建立信任。动态类型不可怕,可怕的是用静态类型的大脑写动态类型的代码。放轻松,让Python做Python该做的事。类型错误会出的,但不是世界末日。改就是了。