前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >PEP8规则及Pycharm应用

PEP8规则及Pycharm应用

作者头像
小歪
发布2018-04-04 15:19:15
1.4K0
发布2018-04-04 15:19:15
举报
文章被收录于专栏:Python爬虫与算法进阶

PEP8

PEP是 Python Enhancement Proposal 的缩写,翻译过来就是 Python增强建议书

PEP8 是什么呢,简单说就是一种编码规范,是为了让代码“更好看”,更容易被阅读。

具体有这些规范,参考 PEP 8 -- Style Guide for Python Code

For example

代码语言:javascript
复制
Yes: import os
     import sys

No:  import sys, os


Yes:
i = i + 1
submitted += 1
x = x*2 - 1
hypot2 = x*x + y*y
c = (a+b) * (a-b)


No:
i=i+1
submitted +=1
x = x * 2 - 1
hypot2 = x * x + y * y
c = (a + b) * (a - b)

对于初学者(例如我)来说,这些标准太多,在实际coding中可能很难记住所有的。之前招聘爬虫工程师,会PEP8也会加分,所以学习下PEP8还是有帮助的。

Pycharm 设置

PyCharm 配置 PEP 8 代码提示 直接在右下角调整 Highlighting Level 为 Inspections 就能自动 PEP 8提示 (一般默认就是这个)

For example

鼠标移到上方会提示: PEP 8: expected 2 blank lines, found 1,我们再增加一个空格就好了,你的代码中有任何不符合 PEP8 规范的地方都会有“~~~~~”提示

这是一个困扰了我很久的问题,我一直不知道是哪里出了错,看英文也不懂,最后去Google才知道,创建字典的写法不规范,应该这样写:

item = dict()

其他工具

除了Pycharm,还有其他工具可以提示

  1. Google 开源的 Python 文件格式化工具:github.com/google/yapf
  2. pyflakes, pylint 等工具及各种编辑器的插件

正文

好吧,这里才是正文,正确的规范如下:

缩进

  • 不要使用 tab 缩进
  • 使用任何编辑器写 Python,请把一个 tab 展开为 4 个空格
  • 绝对不要混用 tab 和空格,否则容易出现 IndentationError

空格

  • 在 list, dict, tuple, set, 参数列表的 , 后面加一个空格
  • 在 dict 的 : 后面加一个空格
  • 在注释符号 # 后面加一个空格,但是 #!/usr/bin/python# 后不能有空格
  • 操作符两端加一个空格,如 +, -, *, /, |, &, =
  • 接上一条,在参数列表里的 = 两端不需要空格
  • 括号((), {}, [])内的两端不需要空格

空行

  • function 和 class 顶上两个空行
  • class 的 method 之间一个空行
  • 函数内逻辑无关的段落之间空一行,不要过度使用空行
  • 不要把多个语句写在一行,然后用 ; 隔开
  • if/for/while 语句中,即使执行语句只有一句,也要另起一行

换行

  • 每一行代码控制在 80 字符以内
  • 使用 \ 或 () 控制换行,举例:
代码语言:javascript
复制
def foo(first, second, third, fourth, fifth,
        sixth, and_some_other_very_long_param):
    user = User.objects.filter_by(first=first, second=second, third=third) \
        .skip(100).limit(100) \
        .all()

text = ('Long strings can be made up '
        'of several shorter strings.')

命名

  • 使用有意义的,英文单词或词组,绝对不要使用汉语拼音
  • package/module 名中不要出现 -
  • 各种类型的命名规范:

import

  • 所有 import 尽量放在文件开头,在 docstring 下面,其他变量定义的上面
  • 不要使用 from foo imort *
  • import 需要分组,每组之间一个空行,每个分组内的顺序尽量采用字典序,分组顺序是:
    1. 标准库
    2. 第三方库
    3. 本项目的 package 和 module
  • 不要使用隐式的相对导入(implicit relative imports),可是使用显示的相对导入(explicit relative imports),如from ..utils import parse,最好使用全路径导入(absolute imports)
  • 对于不同的 package,一个 import 单独一行,同一个 package/module 下的内容可以写一起:
代码语言:javascript
复制
# bad
import sys, os, time

# good
import os
import sys
import time

# ok
from flask import Flask, render_template, jsonify
  • 为了避免可能出现的命名冲突,可以使用 as 或导入上一级命名空间
  • 不要出现循环导入(cyclic import)

注释

  • 文档字符串 docstring, 是 package, module, class, method, function 级别的注释,可以通过 doc 成员访问到,注释内容在一对 """ 符号之间
  • function, method 的文档字符串应当描述其功能、输入参数、返回值,如果有复杂的算法和实现,也需要写清楚
  • 不要写错误的注释,不要无谓的注释
代码语言:javascript
复制
# bad 无谓的注释
x = x + 1       # increase x by 1

# bad 错误的注释
x = x - 1       # increase x by 1
  • 优先使用英文写注释,英文不好全部写中文,否则更加看不懂

异常

  • 不要轻易使用 try/except
  • except 后面需要指定捕捉的异常,裸露的 except 会捕捉所有异常,意味着会隐藏潜在的问题
  • 可以有多个 except 语句,捕捉多种异常,分别做异常处理
  • 使用 finally 子句来处理一些收尾操作
  • try/except 里的内容不要太多,只在可能抛出异常的地方使用,如:
代码语言:javascript
复制
    # bad
    try:
        user = User()
        user.name = "leon"
        user.age = int(age) # 可能抛出异常
        user.created_at = datetime.datetime.utcnow()

        db.session.add(user)
        db.session.commit() # 可能抛出异常
    except:
        db.session.rollback()

    # better
    try:
        age = int(age)
    except (TypeError, ValueError):
        return # 或别的操作

    user = User()
    user.name = "leon"
    user.age = age
    user.created_at = datetime.datetime.utcnow()
    db.session.add(user)

    try:
        db.session.commit()
    except sqlalchemy.exc.SQLAlchemyError: # 或者更具体的异常
        db.session.rollback()
    finally:
        db.session.close()
  • Exception 而不是 BaseException 继承自定义的异常类

Class(类)

  • 显示的写明父类,如果不是继承自别的类,就继承自 object 类
  • 使用 super 调用父类的方法
  • 支持多继承,即同时有多个父类,建议使用 Mixin

编码建议


字符串

  • 使用字符串的 join 方法拼接字符串
  • 使用字符串类型的方法,而不是 string 模块的方法
  • 使用 startswithendswith 方法比较前缀和后缀
  • 使用 format 方法格式化字符串

比较

  • 空的 list, str, tuple, set, dict 和 0, 0.0, None 都是 False
  • 使用 if some_list 而不是 if len(some_list) 判断某个 list 是否为空,其他类型同理
  • 使用 is 和 is not 与单例(如 None)进行比较,而不是用 == 和 !=
  • 使用 if a is not None 而不是 if not a is None
  • 用 isinstance 而不是 type 判断类型
  • 不要用 == 和 != 与 True 和 False 比较(除非有特殊情况,如在 sqlalchemy 中可能用到)
  • 使用 in 操作:
代码语言:javascript
复制
    # bad
    if d.has_key(k):
        do_something()

    # good
    if k in d:
        do_something()
  • 2.用 set 加速 “存在性” 检查,list 的查找是线性的,复杂度 O(n),set 底层是 hash table, 复杂度 O(1),但用 set 需要比 list 更多内存空间
    1. 用 key in dict 而不是 dict.has_key()

其他

  • 使用列表表达式(list comprehension),字典表达式(dict comprehension, Python 2.7+) 和生成器(generator)
  • dict 的 get 方法可以指定默认值,但有些时候应该用 [] 操作,使得可以抛出 KeyError
  • 使用 for item in list 迭代 list, for index, item in enumerate(list) 迭代 list 并获取下标
  • 使用内建函数 sorted 和 list.sort 进行排序
  • 适量使用 map, reduce, filter 和 lambda,使用内建的 all, any 处理多个条件的判断
  • 使用 defaultdict (Python 2.5+), Counter(Python 2.7+) 等 “冷门” 但好用的标准库算法和数据结构
  • 使用装饰器(decorator)
  • 使用 with 语句处理上下文
  • 有些时候不要对类型做太过严格的限制,利用 Python 的鸭子类型(Duck Type)特性
  • 使用 logging 记录日志,配置好格式和级别
  • 了解 Python 的 Magic Method:A Guide to Python’s Magic Methods, Python 魔术方法指南
  • 阅读优秀的开源代码,如 Flask 框架, Requests for Humans
  • 不要重复造轮子,查看标准库、PyPi、Github、Google 等使用现有的优秀的解决方案

反思

写程序的好习惯在于理解、坚持,然后就是运用自如,你说呢?

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2018-02-08,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 Python爬虫与算法进阶 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • PEP8
  • Pycharm 设置
  • 其他工具
  • 正文
    • 缩进
      • 空格
        • 空行
          • 换行
            • 命名
              • import
                • 注释
                  • 异常
                    • Class(类)
                      • 编码建议
                        • 字符串
                          • 比较
                            • 其他
                            • 反思
                            领券
                            问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档