假如你是一个pythoner,你可以忍受下面的这段代码么?(当然,这是我为了举例乱写的,现实中应该没人这么写)

class Person1:
   
   def __init__(self, BALL):
      self.eatFood()
      self.drink_water()
      self.ball = BALL
      self.PlayBall(self.ball)
   
   def eatFood(self):
     print("eat_food")
   
   def drink_water(self):
     print("Drink_water")
   
   def PlayBall(self, Ball):
     content = "i'm play {}".fomat(Ball)
     print(content)

好吧,估计你也会看不下去,今天就来聊聊,python的编程风格。

 

本文参考的是 Google 版本的 Python 编程风格。

原文地址:https://google.github.io/styleguide/pyguide.html

原文实在是太长了,下面我就走马观花的介绍一下,假如感兴趣的,可以自行查看原文。

 

01、遵循pylint

pylint是一个检查python编程风格的工具,要求代码要通过pylint检测。

 

一般的IDE工具,比如Pycharm、VSCode,都有或者可安装pylint插件。

 

 

02、命名

函数名称,变量名称和文件名应具有描述性;避开缩写。

 

特别是,请勿使用项目外部读者不清楚或不熟悉的缩写,也不要通过删除单词中的字母来进行缩写。

 

龟叔要求的命名法则

Type Public Internal
包名 lower_with_under  
模块名 lower_with_under _lower_with_under
类名 CapWords _CapWords
异常名 CapWords  
函数名 lower_with_under() _lower_with_under()
全局/类常量 CAPS_WITH_UNDER _CAPS_WITH_UNDER
全局/类变量 lower_with_under _lower_with_under
实例变量 lower_with_under _lower_with_under (protected)
方法名 lower_with_under() _lower_with_under() (protected)
方法/函数 参数 lower_with_under  
本地变量 lower_with_under  

 

应该避免的名称:

(1)避免单个字符的名称,异常“e”除外

YES

name = "小明"

NO

n = "小明"

 

(2)避免任何程序包/模块名称中的破折号()

YES

文件命名:test_2020_02_05.py

NO

文件命名:test-2020-02-05.py


(3)避免双下划线(__)包裹的变量名称(由python保留)

YES

age = 27

NO

__age__ = 27

 

03、True 和 False

在使用判断语句时,尽量使用“隐式假”。

在Python中,0, None, [], {}, ' '在布尔值上下文中,值都为 False。

使用Python布尔值的条件更易于阅读且不易出错。在大多数情况下,运行速度也更快。

 

YES

if not users:
    print('no users')
if foo == 0:
    self.handle_zero()
if i % 10 == 0:
    self.handle_multiple_of_ten()
def f(x=None):
    if x is None:
        x = []

NO

if len(users) == 0:
    print('no users')
if foo is not None and not foo:
    self.handle_zero()
if not i % 10:
    self.handle_multiple_of_ten()
    
def f(x=None):
    x = x&nbs***bsp;[]

 

04、分号

不要用分号终止行,也不要使用分号在同一行上放置两个语句。

 

05、单行语句长度

最大行长度为80个字符,以下几种情况除外:

  • 长 import 语句。

  • 注释中的URL,路径名或长标记。

  • 长字符串模块级别的常量不包含空格,这些常量不方便在URL或路径名等行之间进行拆分。

  • Pylint禁用注释。(如:# pylint: disable=invalid-name)

 

除非with需要三个或更多上下文管理器的语句,否则不要使用反斜线继续。

可利用括号隐式分割。

YES

foo_bar(self, width, height, color='black', design=None, x='foo',
             emphasis=None, highlight=0)
if (width == 0 and height == 0 and
         color == 'red' and emphasis == 'strong'):

YES

x = ('This will build a very long long '
     'long long long long long long string')

YES

# See details at
# http://www.example.com/us/developer/documentation/api/content/v2.0/csv_file_name_extension_full_specification.html

NO

# See details at
# http://www.example.com/us/developer/documentation/api/content/\
# v2.0/csv_file_name_extension_full_specification.html

 

06、缩进

代码块缩进4个空格。

切勿使用制表符或将制表符和空格混用。

 

 

07、空行

import语句下面接两个空行

import os



def Xxx():
    pass

方法定义之间有一个空行

def add():
    pass
    
def multiplication():
    pass

 

class 与 def 之间,有一个空行

class Person:

    def eat(self):
        pass

 

08、空格

括号,方括号或大括号内没有空格。

YES

spam(ham[1], {eggs: 2}, [])

NO

spam( ham[ 1 ], { eggs: 2 }, [ ] )

 

逗号,分号或冒号前没有空格;逗号,分号或冒号后有空格。

YES

if x == 4:
    print(x, y)
    x, y = y, x

NO​​​​​​​

if x == 4 :
    print(x , y)
    x , y = y , x

 

以下运算符两侧各有一个空格

赋值运算符(=)

比较运算符(==, <, >, !=, <>, <=, >=, in, not in, is, is not)

布尔值(and, or, not)

算术运算符(+,-,*,/,//,%,**,@)

YES

x == 1

NO

x<1

 

= 传递关键字参数或定义默认参数值时,切勿使用空格;

但有一个例外:当存在类型注释时,请=在默认参数值的周围使用空格。

YES​​​​​​​

def complex(real, imag=0.0): return Magic(r=real, i=imag)
def complex(real, imag: float = 0.0): return Magic(r=real, i=imag)

NO 

def complex(real, imag = 0.0): return Magic(r = real, i = imag)
def complex(real, imag: float=0.0): return Magic(r = real, i = imag)

 

不要使用空格作为连续的行上垂直对齐的标记,

因为它会造成维护负担(适用于:,#,=,等)

YES​​​​​​​

foo = 1000  # comment
long_name = 2  # comment that should not be aligned

dictionary = {
    'foo': 1,
    'long_name': 2,
}

NO

foo       = 1000  # comment
long_name = 2     # comment that should not be aligned

​​​​​​​dictionary = {
    'foo'      : 1,
    'long_name': 2,
}

 

09、类

大体上和函数格式一致,以下是标准的书写格式范例:

class SampleClass(object):
    """Summary of class here.
    Longer class information....
    Longer class information....
    Attributes:
        likes_spam: A boolean indicating if we like SPAM or not.
        eggs: An integer count of the eggs we have laid.
    """
​​​​​​​
    def __init__(self, likes_spam=False):
        """Inits SampleClass with blah."""
        self.likes_spam = likes_spam
        self.eggs = 0
    def public_method(self):
        """Performs operation blah."""

 

10、字符串

使用format方法或%运算符格式化字符串,避免使用+或+=拼接字符串

YES​​​​​​​

x = a + b
x = '%s, %s!' % (imperative, expletive)
x = '{}, {}'.format(first, second)
x = 'name: %s; score: %d' % (name, n)
x = 'name: {}; score: {}'.format(name, n)
x = f'name: {name}; score: {n}'  # Python 3.6+

NO​​​​​​​

x = '%s%s' % (a, b)  # use + in this case
x = '{}{}'.format(a, b)  # use + in this case
x = first + ', ' + second
x = 'name: ' + name + '; score: ' + str(n)

 

11、引入模块

引包顺序:

先引入标准库,

再引入三方库,

最后引入自己代码的库。

import collections
import queue
import sys

​​​​​​​from absl import app
from absl import flags
import bs4
import cryptography
import tensorflow as tf

from book.genres import scifi
from myproject.backend.hgwells import time_machine
from myproject.backend.state_machine import main_loop
from otherproject.ai import body
from otherproject.ai import mind
from otherproject.ai import soul

# Older style code may have these imports down here instead:
#from myproject.backend.hgwells import time_machine
#from myproject.backend.state_machine import main_loop

 

12、函数长度

偏爱小型且专注的功能。

函数长度没有硬性限制。如果一个函数超过40行,请考虑是否可以在不破坏程序结构的情况下将其分解。

 

关于作者

github:https://github.com/GitDzreal93/dev-tester
微信公众号:测试开发guide