Python 新手容易踩的坑

根据 How to Make Mistakes in Python 一书,以及我自己的经验,总结了 Python 新手容易踩的坑。

配置

直接 pip install 把包安装在 site-packages 目录下,容易导致冲突。一定要养成配置虚拟环境的习惯,例如 virtualenv,不过我更习惯用 conda(在这之前我也搞坏过别人的环境……)。

不要用自带的 REPL,建议改用 IPython/Jupyter Notebook。

手滑

写函数的时候不要忘记返回值。关于测试,不要偷懒。

使用支持自动补全的编辑器,最好支持代码检查,例如未定义、未使用变量,从而避免手滑带来的难以发觉的错误。

风格

没有必要用匈牙利命名法对每个变量写出它的类型,这对代码逻辑没有实质帮助,反而会把变量名搞得很长。关于命名和其他代码习惯问题,我推荐阅读 The Art of Readable Code(编写可读代码的艺术)。

了解 PEP-8。

不要滥用 lambda 语句。

结构

如果有类似 switch case 的需求,用过多的 if/elif/else 可能看起来混乱。建议用字典映射到所采取的选择,或者采用面向对象的方式。

没有必要像 Java 那样写一大堆 getter/setter。如果想要私有属性,善用 @property

@property
def event_number(self):
    return self._event_number

@event_number.setter
def _set_event_number(self, x):
    self._event_number = int(x)

@event_number.deleter
def _delete_event_number(self):
    self._event_number = None

event.event_number = 10    
print(event.event_number)

遵循 The Law of Demeter,减少不必要的耦合,更不要将耦合隐藏在深处。

不要滥用全局状态。

意外

不要 from some_module import *,否则你无法掌控 import 了哪些东西。一个折中的方法是在 some_module 里面定义 __all__ = ['foo', 'bar', ...],这样 import * 就只会引入它们。不过根本上还是建议彻底摒弃 import *

不要在 import 的时候做高代价、高依赖的事情,例如在 __init__.py 或者模块的开头部分从数据库读入,后果是慢而且容易出错,导致模块的其他函数也无法 import

不要滥用 try: .... except: pass,因为这样会导致所有的错误(及其发生的上下文)都无声无息掩盖过去。正确的做法是指明 except Exception 或者 except IOError,并且记录 logging.exception('message')

造轮子之前,查找标准库、PyPI 和 GitHub。

警惕 mutable 变量作为缺省的关键字参数,非常不安全,例如

def set_reminders(self, event, reminders=[]):
    reminders.extend(self.get_default_reminders())
    for reminder in reminders:
        ...

这样写的结果是多次调用之后 reminders 变得非常长,每次调用它的信息都积累下来,非常可能导致隐私泄露。这是因为列表是 mutable 变量,同一个 instance 贯穿始终。应该采用 immutable 变量,保证每次调用都是一个新的 instance,例如

def set_reminders(self, event, reminders=None):
    reminders = reminders or []
    # 或者 reminders = [] if reminders if None else reminders
    reminders.extend(self.get_default_reminders())
    for reminder in reminders:
        ...

重视 logging,重视测试,不要找借口偷懒。



Previous     Next
sighsmile /
Published under (CC) BY-NC-SA