社区所有版块导航
Python
python开源   Django   Python   DjangoApp   pycharm  
DATA
docker   Elasticsearch  
aigc
aigc   chatgpt  
WEB开发
linux   MongoDB   Redis   DATABASE   NGINX   其他Web框架   web工具   zookeeper   tornado   NoSql   Bootstrap   js   peewee   Git   bottle   IE   MQ   Jquery  
机器学习
机器学习算法  
Python88.com
反馈   公告   社区推广  
产品
短视频  
印度
印度  
Py学习  »  Python

个人总结——全面的『Python编码规范』

hezhiming • 7 年前 • 399 次点击  

个人总结——全面的『Python编码规范』

本文目的

『动态类型一时爽,代码重构火葬场』,说的是:动态语言在初期开发比较爽,但是到后期维护起来比较困难。Python 作为动态语言之一,自然也会有这样的缺点。其实说『火葬场』,也没有那么严重,只要严格的遵守一组规范,也能做到『重构的时候,也一样爽』。

不以规矩不成方圆,规范自然是十分重要的,而在动态语言中,尤其重要(很多人拿Python写脚本,基本是随心所欲地写,自然后期维护困难)。所谓『兵马未动粮草先行』,我们应该在写代码前,就做好充足的 “表面功夫”。

本文不涉及哪些

不做『文档复读机』。PEP 8中已经有了的,就不重复了,复述一些“低级(大家都知道了的)” 内容,没啥意思。

不迷信权威,这里指『Google Python Guide』,那是适合Google的规范,并不是社区规范,其实我觉得这份规范既不完整,同时,净是一些『众人皆知』的内容,并不推荐之。

不搞宗教信仰,奉承实用主义。比如典型的『import this』,只有我一个人觉得不过是一堆空洞的废话吗,况且 Python 标准库中很多地方,也没有做到『import this』 中的『simple, explicit, and powerful』。每次各种文章(无节操的营销文章,以各种培训机构为主体)提及这个东西,我真是浑身不自在&尴尬(写代码是很工程很严肃的事情,搞这种玄学干嘛呢)。

适用范围 & 原则

  • Python 2.7 - Python 3.x 。虽然官方宣布了 Python 2的寿命是2020,而且似乎现在 Python 3已经是主流了。但是同学,legacy code 可不是说去掉就去掉的,Python 2仍然会存在相当长一段时间。况且,Python 3 有相对于 Python 2 的 『killer feature』 吗,并没有。
  • 以 PEP 8 为蓝本,紧紧团结在 PEP 8 周围。任何非官方的文档,只是参考之(同理,本文亦是某种参考资料)。
  • PEP 8 已经有了的,就不要重复了。

规范

【强制 + 强制】【挑选『静态检查』工具,并自始至终都严格使用】

简单来说,就是:
1. Pylint
2. Flake8
3. pytest

一开始就要使用,并且从严使用(发点时间了解这几个工具,带来的收益是无限的,如果你是比较正式的项目的话)。

【强制+】【多写UT】

其他编程语言,同理。

有一份UT在手,重构起来,心里放心很多。

Python的话,只需要了解unittest就够了,pytest也可以。

【强制】【文件编码 & Unicode】:

  1. 使用 4 空格缩进,禁用任何 TAB 符号
  2. 源码文件使用 UTF-8 无 BOM 编码格式
  3. 总是使用 Unix \n 风格换行符
  4. 在每一个 py 文件头,都添加如下内容:
#!/usr/bin/env python
# -*- coding: utf-8 -*-
#
 

# 只导入 future 空间的这两个特性就够了,其他特性容易造成其他方面的『不兼容』,没有使用的必要性。
from __future__ import (absolute_import, unicode_literals)

【强制】【命名】

  1. class,function 该如何命名,不赘述,严格照着PEP8做就行了,不用多想。
  2. 全局变量(全局变量,一般是常量,我们认为:凡是全局的,都是常量),应该始终使用全大写,如:
GLOBAL_PUBLIC = "G1"
_GLOBAL_PRIVATE = "G2"

class Person:
    _GLOBAL_IN_CLASS = 'G3'
    

按照这条要求,其实很多库or开源库,都是不符合要求的。为什么这么强硬呢?
Python中的变量定义,是不分『声明』、『定义』、『初始化』、『赋值』这几个概念的,所以一个
a = 1
如果没有上下文,你是很难确定其作用域的,也很难确定 这到底是初始化还是赋值(a已经存在过),
如果全局变量还不用全大写,带来的麻烦只会更多。

如果始终坚持这个原则,将会给代码的可读性带来极大提升。
  1. 定义枚举,始终加 Enum后缀;定义异常始终加Exception后缀;定义mixin,始终加Mixin后缀,如
class DirectionEnum:
    UP = 1
    DOWN = 2
    
    
class MyException(Exception):
    pass
class MyError(Exception):
    pass
    
class SomeMixin:
    pass

【强制】【强化private的概念】

即:最小知识原则,对外暴露的东西越少越好

翻译成大白话就是:
1. 实例属性,一般定义成private的
2. class,对外提供的方法越少越好
3. module,对外提供的接口越少越好
4. package,对外提供的 module 越少越好

翻译成代码就是:
1. 项目布局
package/
    __init__.py
    _private_mod.py
    public_mod.py    
    
2. 某模块内容
public_mod.py
PUBLIC_GLOBAL = 'G1'
_PRIVATE_GLOBAL = 'G2'
class _Class:
    pass
class PublicClass:
    _PRIVATE_GLOBAL = 'G3'
    
    def __init__(self, name,age):
        self._name = name
        self._age = age
    def public_method(self):
        pass
    def _private(self):
        pass
        

所有东西,一开始就要定义成私有的,等到确实需要开放访问了,才开放出去。

【强制&重要】【关注公开接口的复杂性】

最好的接口是这样的,调用者无脑使用
def interface():
    pass
    
次等接口是这样的
def interface(param1):
    pass
    
次次等接口是这样的
def interface(p1, p2):
    pass

最大忍受限度的接口是这样的
def interface(p1, p2, p3='SOME DEFAULT'):
    pass
def interface(p1, *args):
    pass
    
不可接受的接口是这样的
def interface(p1, p2, **kwargs):
    pass

令人无语的接口是这样的
def interface(*args, **kwargs):  
# 尽量不要使用 **kwargs, 某些流行库有这样的毛病,我是觉得:极大地增加了调用者的心理负担,反映了接口设计者的懒惰
    pass
    
一直觉得,**kwargs只适用于极少数明确的场合,并且需要辅以很明确的文档说明(解释为什么要使用),然而现实是,这个
特性已经被大家滥用了,有必要单独说明之。

【推荐】【以package去设计命名空间,而不是基于module】

【推荐】【了解如下内容】

__init__.py 的作用

__main__.py 的作用

if __name__ == '__main__': 的作用

Python的命名空间加载机制,即:sys.path sys.modules 的内容

【推荐】【合理设计项目目录结构】

如果是使用某种框架(如Django),那么按照框架的规范来;如果是“非框架”项目,则按照如下结构

project
    project/
        __init__.py
        core/
        utils/
        constants/
        
        
        __main__.py
        
    tests/
    docs/
    examples/
    README.md
    .pylintrc
    .flake8
    

今天看啥 - 高品质阅读平台
本文地址:http://www.jintiankansha.me/t/jmLfzcbVCi
Python社区是高质量的Python/Django开发社区
本文地址:http://www.python88.com/topic/12177
 
399 次点击