请按规范写Python

news2024/11/26 9:49:07

一、写在前面

代码被阅读的次数远多于编写的次数。

我们可能花费很多时间来编写一段代码,一旦完成后大概率就再不会重新写它。当这段代码不仅是自己用时,就得注意了,每次自己或其他人浏览,需要快速知道它的作用及编写它的原因,因此可读性显得很重要,比如:

>>> a = "Cai Xukun"
>>> b, c = a.split()
>>> print(b, c, sep=', ')

看到这种脑阔痛。那么,每个人都有自己的编码风格,如何使整个团队趋于一致呢?Python PEP 8早已考虑到这种情况:https://peps.python.org/pep-0008/。

我们可能互相不清楚每个人的风格,但又必须阅读与理解各自产出的代码,那么此时遵循PEP 8会是优秀选择,也是每个Python从业者需要学习掌握的规范,一起看看吧!

二 、命名规范

编写代码时需要命名很多东西,如变量、函数、类等。选择合理的名称将节省以后的时间和精力,确保能够从名称中得到某个变量或函数代表的意义,不恰当的名称还会徒增调试难度。

Tip:切勿使用 l 、 O 或 I 单字母名称,因为这些名称可能会被误认为 1 和 0。

1.命名风格

以下是一些常见的命名约定以及如何使用示例,除了在代码中选择正确的命名样式之外,还必须仔细选择名称:

类型

命名约定

例子

Variable

使用小写的单个字母、单词或单词,用下划线分隔单词

x, var, my_variable

Function

使用一个或多个小写单词,用下划线分隔单词

function, my_function

Class

每个单词都以大写字母开头,这种风格称为驼峰式命名法或帕斯卡式命名法

Model, MyClass

Method

使用一个或多个小写单词,用下划线分隔单词

class_method, method

Constant

使用大写的单个字母、单词或单词,用下划线分隔单词

CONSTANT, MY_CONSTANT, MY_LONG_CONSTANT

Module

使用简短的小写单词,用下划线分隔单词

module.py, my_module.py

Package

使用简短的小写单词,不要用下划线分隔单词

package, mypackage

2.如何选择名字

在编写代码时对命名选择需要进行足够的思考,在Python中为对象命名的最佳方法是使用描述性的名称。

在命名变量时,可能会选择简单的、单个字母的小写名称。比如这篇文章开头的引例,要将一个人的姓名存储为字符串,并且想要使用字符串切片来以不同的方式格式化姓名吗,写成如下形式是不是更舒服?

>>> name = 'Cai Xukun'
>>> first_name, last_name = name.split()
>>> print(last_name, first_name, sep=', ')

同样地,为了偷懒,你可能在选择名称时使用缩写。如下示例中,定义了一个名为db()的函数,它接受一个参数x并将其乘2倍,乍一看,这似乎是一个明智的选择,db()是double的缩写,但在一段时间后再回到这段代码,可能已经忘记了这个函数实现什么,并为偷懒付出相应代价:

def db(x):
    return x * 2

以下写法则要清晰得多:

def multiply_by_two(x):
    return x * 2

相同的原则也适用于Python中所有其他数据类型和对象,始终尽量使用最简洁且具有描述性的名称总不会出错。

三、代码排版布局

垂直空白,即空行,对于提升代码的可读性起着关键作用。密集堆叠的代码可能令人感到压抑,不易理解,同样地,代码中过多的空行则会让其看起来过于稀疏,带来不必要的滚动。

将顶层函数和类用两个空行隔开。顶层函数和类通常相对独立,承担不同的功能。因此,为其周围添加适量的垂直空间是合理的,这有助于清晰地标示它们的独立性:

class MyFirstClass:
    pass


class MySecondClass:
    pass


def top_level_function():
    return None

用一个空行分隔类内方法定义:

class MyClass:
    def first_method(self):
        return None

    def second_method(self):
        return None

在函数内部使用空行以展示清晰的步骤。有时,一个复杂的函数在return之前需要完成多个步骤。为了帮助读者理解函数内部的逻辑,每个步骤之间留出一个空行会很有帮助。

在下面的示例中,有一个计算列表方差的函数。这是一个两步问题,通过在它们之间留出空行来表示每个步骤。在return之前也有一个空行,有助于清楚地看到返回了什么内容:

def calculate_variance(number_list):
    sum_list = 0
    for number in number_list:
        sum_list = sum_list + number
    mean = sum_list / len(number_list)

    sum_squares = 0
    for number in number_list:
        sum_squares = sum_squares + number**2
    mean_squares = sum_squares / len(number_list)

    return mean_squares - mean**2
1.最大行长度和换行

PEP 8建议将行限制在79个字符以内,但很多时候将语句限制在79个字符或更少并不总是可能的。PEP 8概述了语句跨越多行的方法。

如果代码包含在括号、方括号或花括号内,Python会假定它是行的延续:

def function(arg_one, arg_two,
             arg_three, arg_four):
    return arg_one

还可以使用反斜杠来换行:

from mypkg import example1, \
    example2, example3

如果需要在二元操作符(如+和)周围进行换行,应该在操作符之前进行*。这个规则源自数学,数学家们一致认为,在二元操作符之前换行可以提高可读性,可以立即看到正在相加或相减的变量,因为操作符紧邻正在操作的变量:

total = (first_variable
         + second_variable
         - third_variable)

现在,让我们看一个在二元操作符之后换行的示例:

total = (first_variable +
         second_variable -
         third_variable)

在这里,很难看出正在相加的变量和正在相减的变量。

在二元操作符之前换行会产生更可读的代码,因此PEP 8鼓励这样做。

2.缩进

缩进在Python中非常重要。在Python中,代码行的缩进级别决定了语句如何分组在一起。

考虑以下示例:

x = 3
if x > 5:
    print('x is larger than 5')

缩进的打印语句告诉Python只有在if语句返回True时才执行它。相同的缩进规则适用于在调用函数时告诉Python要执行哪些代码,或者哪些代码属于给定的类。

PEP 8规定的关键缩进规则如下:

  • 使用4个连续的空格来表示缩进
  • 优先选择空格而不是制表符
3.制表符 vs. 空格

如上所述,在缩进代码时应该使用空格而不是制表符。当按下Tab键时,可以调整文本编辑器的设置,将制表符字符输出为4个空格。

Python 3不允许混合使用制表符和空格。如果正在使用Python 3,则会抛出这些错误:

$ python3 code.py
  File "code.py", line 3
    print(i, j)
              ^
TabError: inconsistent use of tabs and spaces in indentation

可以使用制表符或空格来指示缩进的Python代码。但是,如果使用的是Python 3,必须在选择上保持一致,否则,代码将无法运行。

4.换行后的缩进

当使用行延续将行保持在79个字符以下时,使用缩进来提高可读性非常有用。帮助区分两行代码和跨越两行的单行代码。可以使用两种缩进样式,第一种是将缩进块与起始分隔符对齐:

def function(arg_one, arg_two,
             arg_three, arg_four):
    return arg_one

有时,只需要4个空格与起始分隔符对齐。这通常发生在跨多行的if语句中,因为if、空格和起始括号共计4个字符。在这种情况下,很难确定if语句内部的嵌套代码块从哪里开始:

x = 5
if (x > 3 and
    x < 10):
    print(x)

在这种情况下,PEP 8提供了两种改进可读性的替代方法:

  • 在最终条件之后添加注释。由于大多数编辑器中的语法高亮,这将把条件与嵌套代码分开
x = 5
if (x > 3 and
    x < 10):
    # Both conditions satisfied
    print(x)
  • 在行延续上添加额外的缩进
x = 5
if (x > 3 and
        x < 10):
    print(x)

换行后的另一种缩进样式是悬挂缩进,悬挂缩进即段落或语句中除了第一行外的每一行都缩进。可以使用悬挂缩进来在视觉上表示代码行的延续:

var = function(
    arg_one, arg_two,
    arg_three, arg_four)

当使用悬挂缩进时,第一行不得有任何参数。

使用悬挂缩进时,添加额外的缩进以区分连续的行与函数内部的代码。如以下示例很难阅读,因为函数内部代码与连续的行处于相同的缩进级别:

def function(
    arg_one, arg_two,
    arg_three, arg_four):
    return arg_one

相反,最好在行延续上使用双重缩进。这有助于区分函数参数和函数体,提高可读性:

def function(
        arg_one, arg_two,
        arg_three, arg_four):
    return arg_one
5.右括号怎么处理

行延续允许在括号、方括号或大括号内换行。但很容易忽略闭合括号的位置,将它放在合适的地方很重要。PEP 8提供了两个选项来确定隐式行延续中闭合括号的位置。

将闭合括号与前一行的第一个非空白字符对齐:

list_of_numbers = [
    1, 2, 3,
    4, 5, 6,
    7, 8, 9
    ]

将闭合括号与开始构造的行的第一个字符对齐:

list_of_numbers = [
    1, 2, 3,
    4, 5, 6,
    7, 8, 9
]

可以自由选择使用哪个选项,但请保持一致。

四、注释

使用注释来记录代码的编写以便自己和任何合作者都能理解。在添加注释到代码时,请记住以下要点:

  • 将注释和文档字符串的行长度限制在72个字符以内
  • 使用完整的句子,以大写字母开头。
  • 确保在更改代码时更新注释
1.块注释

块注释非常有用,帮助他人理解给定代码块的目的和功能,PEP 8为编写块注释提供以下规则:

  • 将块注释的缩进与它们描述的代码保持一致
  • 每行以#开头,后跟一个空格
  • 使用只包含一个#的行来分隔段落

以下是解释for循环功能的块注释示例。为保持79字符行限制,句子被换行:

for i in range(0, 10):
    # Loop over i ten times and print out the value of i, followed by a
    # new line character
    print(i, '\n')

有时,如果代码技术含量高,那么在块注释中使用多个段落是必要的:

def quadratic(a, b, c, x):
    # Calculate the solution to a quadratic equation using the quadratic
    # formula.
    #
    # There are always two solutions to a quadratic equation, x_1 and x_2.
    x_1 = (- b+(b**2-4*a*c)**(1/2)) / (2*a)
    x_2 = (- b-(b**2-4*a*c)**(1/2)) / (2*a)
    return x_1, x_2

如果不确定哪种注释类型适合,通常可以选择使用块注释。

2.行内注释

行内注释用于解释代码片段中的单个语句。以下是PEP 8关于行内注释的建议:

  • 适度使用行内注释
  • 将行内注释写在与其引用的语句同一行上
  • 将行内注释与语句之间用两个或更多空格分隔开
  • 与块注释一样,以#和一个空格开头
  • 不要用它们来解释显而易见的事情

以下是行内注释的示例:

x = 5  # This is an inline comment

有时,行内注释是必要的,但可以使用更好的命名约定来替代:

x = 'John Smith'  # Student Name

在这个示例中,行内注释确实提供了额外的信息。但是,将“x”作为人名的变量名是很呆的做法,如果更改变量名称,就不需要行内注释:

student_name = 'John Smith'

最后,诸如以下的行内注释是不好的习惯(脱裤子放P),因为陈述了显而易见的事实并且会使代码混乱:

empty_list = []  # Initialize empty list

x = 5
x = x * 5  # Multiply x by 5
3.文档字符串

文档字符串,docstrings,是出现在任何函数、类、方法或模块的第一行的双引号(“”")或单引号(‘’')括起来的字符串。用于解释和记录特定的代码块。PEP 257有专门阐述docstrings,docstrings最重要规则如下:

  • 在docstrings两侧使用三个双引号,如 “”“这是一个docstring”“”
  • 为所有公共模块、函数、类和方法编写docstrings
  • 将终止多行docstring的"""单独放在一行上
def quadratic(a, b, c, x):
    """Solve quadratic equation via the quadratic formula.

    A quadratic equation has the following form:
    ax**2 + bx + c = 0

    There always two solutions to a quadratic equation: x_1 & x_2.
    """
    x_1 = (- b+(b**2-4*a*c)**(1/2)) / (2*a)
    x_2 = (- b-(b**2-4*a*c)**(1/2)) / (2*a)

    return x_1, x_2
  • 对于单行docstrings,请将"""保持在同一行上
def quadratic(a, b, c, x):
    """Use the quadratic formula"""
    x_1 = (- b+(b**2-4*a*c)**(1/2)) / (2*a)
    x_2 = (- b-(b**2-4*a*c)**(1/2)) / (2*a)

    return x_1, x_2

五、表达式中的空格

在表达式和语句中适当使用空格可以非常有助于阅读。如果没有足够的空格,代码可能会难以阅读,因为它们都挤在一起。如果空格过多,则在语句中可能很难在视觉上组合相关术语。

1.二元操作符周围的空格

在以下二元操作符的两侧都加上单个空格:

  • 赋值操作符(=,+=,-=等)
  • 比较(==,!=,>,<,>=,<=)和(is,is not,in,not in)
  • 布尔运算(and,not,or)

Tip:当使用 = 为函数参数分配默认值时,不要用空格如:def function(default_parameter=5):

当语句中有多个操作符时,在每个操作符前后都添加单个空格可能会显得混乱。相反,最好只在具有最低优先级的操作符周围添加空格,特别是在进行数学操作时。以下是几个示例:

# Recommended
y = x**2 + 5
z = (x+y) * (x-y)

# Not Recommended
y = x ** 2 + 5
z = (x + y) * (x - y)

还可以将此应用于具有多个条件的if语句:

# Not recommended
if x > 5 and x % 2 == 0:
    print('x is larger than 5 and divisible by 2!')

在上面的示例中,and操作符具有最低优先级。因此,以下方式可能更清晰地表示:

# Recommended
if x>5 and x%2==0:
    print('x is larger than 5 and divisible by 2!')

可以自由选择哪种更清晰,但请注意,操作符两侧必须使用相同数量的空格。

在切片中,冒号充当二元操作符。因此,适用于前一节中概述的规则,两侧应具有相同数量的空格:

list[3:4]

# Treat the colon as the operator with lowest priority
list[x+1 : x+2]

# In an extended slice, both colons must be
# surrounded by the same amount of whitespace
list[3:4:5]
list[x+1 : x+2 : x+3]

# The space is omitted if a slice parameter is omitted
list[x+1 : x+2 :]
2.何时避免添加空格

在某些情况下,添加空格可能会使代码更难阅读。PEP 8明确提供了一些不适合使用空格的示例。

最容易出Bug的是在行末,即尾随空格。因为它是不可见的,可能会产生难以追踪的错误,以下概述了一些应避免添加空格的情况:

  • 紧跟在括号、方括号或花括号内:
# Recommended
my_list = [1, 2, 3]

# Not recommended
my_list = [ 1, 2, 3, ]
  • 在逗号、分号或冒号之前:
# Recommended
print(x, y)

# Not recommended
print(x , y)
  • 在函数参数列表左括号之前:
def double(x):
    return x * 2

# Recommended
double(3)

# Not recommended
double (3)
  • 在索引或切片的左括号之前:
# Recommended
list[3]

# Not recommended
list [3]
  • 在尾随逗号和闭合括号之间:
# Recommended
tuple = (1,)

# Not recommended
tuple = (1, )
  • 用于对齐赋值操作符:
# Recommended
var1 = 5
var2 = 6
some_long_var = 7

# Not recommended
var1          = 5
var2          = 6
some_long_var = 7

六、编程建议

1.不要使用等价运算符将布尔值与True|False进行比较
# Not recommended
my_bool = 6 > 5
if my_bool == True:
    return '6 is bigger than 5'

在这里使用等价运算符(==)是不必要的,bool只能取True或False的值,以下写法已足够,PEP 8鼓励使用它:

# Recommended
if my_bool:
    return '6 is bigger than 5'

如果要检查列表是否为空,首先会想要检查列表的长度,如果列表为空,它的长度为0,在if语句中使用时等效于False:

# Not recommended
my_list = []
if not len(my_list):
    print('List is empty!')

然而,在Python中,任何空列表、字符串或元组都是False。因此,可以找到一个更简单的替代方案:

# Recommended
my_list = []
if not my_list:
    print('List is empty!')

虽然这两个示例都会输出"List is empty!",PEP 8鼓励使用第二个方式。

2.在if语句中,使用"is not"而不是"not … is"
# Recommended
if x is not None:
    return 'x exists!'

不要写成以下形式:

# Not recommended
if not x is None:
    return 'x exists!'

在检查字符串是否以特定词开头或结尾时,使用.startswith()和.endswith()而不是切片:

# Not recommended
if word[:3] == 'cat':
    print('The word starts with "cat"')

使用.startswith():

# Recommended
if word.startswith('cat'):
    print('The word starts with "cat"')

同样的原则也适用于检查后缀:

# Recommended
if file_name.endswith('jpg'):
    print('The file is a JPEG')

以上就是本期的全部内容,如果想了解更多关于PEP 8的细节可以访问:https://pep8.org/。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1182759.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

集合框架:List系列集合:特点、方法、遍历方式、ArrayList,LinkList的底层原理

目录 List集合 特有方法 遍历方式 1. 使用普通 for 循环&#xff1a; 2. 使用增强型 for 循环&#xff08;foreach&#xff09;&#xff1a; 3. 使用迭代器&#xff08;Iterator&#xff09;&#xff1a; 4. 使用 Java 8 的流&#xff08;Stream&#xff09;API&#xff…

Sketch是什么软件,如何收费和获得免费版

Sketch软件为设计师构建了一个优秀的本地Mac应用程序。Sketch是整个设计过程的平台&#xff0c;通过基于Web的工具共享工作&#xff0c;获取反馈&#xff0c;测试原型&#xff0c;并将其移交给任何浏览器。Sketch软件的定价根据不同的许可类型和订阅计划而变化。本文从Sketch软…

微信小程序:怎么在一个js中修改另一个js的数据(这里通过缓存进行实现)

实例&#xff1a;现有两个页面index.js和category.js,我现在想在index.js中修改category.js的数据 初始数据 category [{name: 物流配送,list: [{id: 1,job: 外卖骑手,checked: true}, {id: 2,job: 快递员,checked: false}, {id: 3,job: 司机,checked: false}, {id: 4,job: …

Spring Cloud - 通过 Gateway webflux 编程实现网关异常处理

一、webflux 编程实现网关异常处理 我们知道在某一个服务中出现异常&#xff0c;可以通过 ControllerAdvice ExceptionHandler 来统一异常处理&#xff0c;即使是在微服务架构中&#xff0c;我们也可以将上述统一异常处理放入到公共的微服务中&#xff0c;这样哪一个微服务需要…

供应链金融融资模式

目录 应收账款融资 库存融资 预付款融资 舍得,只舍不得的人时领袖,先舍后得的人是老板,而只得不舍的人唯有乞丐。 应收账款融资 上游企业(供应商、卖方)为取得运营资金,以与买方(核心企业)签订的贸易合同产生的应收账款为基础,为卖方提供以合同项下的应收账款作为还款…

SSM项目与Redis整合以及Redis注解式开发以及Redis击穿穿透雪崩

目录 前言 一、SSM项目整合Redis 1.导入pom依赖 2.Spring-redis相关配置 3.Spring上下文配置 二、redis注解式缓存 1.Cacheable 注解 2.CachePut 注解 3.CacheEvict 注解 三、redis击穿、穿透、雪崩 1. 缓存击穿 2. 缓存穿透 3. 缓存雪崩 前言 当将SSM项目与Red…

【算法设计实验二】分治法解决棋盘覆盖问题

import java.util.*;public class Main {static int cnt0;public static void main(String[] args){Scanner scnew Scanner(System.in);System.out.println("请输入棋盘边长大小&#xff01;");int nsc.nextInt();int[][] gnew int[n][n];System.out.println("请…

word图片的标题跑到了图片的上方。

问题描述&#xff1a;在写论文时&#xff0c;在word文档中插入了一个svg图片&#xff0c;然后在图片下方输入标题。后面可能是调整了svg图片的大小&#xff0c;标题跑到了图片的上方。 具体情况如下图所示。标题明显跑到了图片的上方。 解决办法&#xff1a;把svg图片格式调成…

RTC实时时钟——DS1302

DS1302目录 一、DS1302简介引脚定义与推荐电路 二、芯片手册1.操作寄存器的定义2.时序定义dc1302.cds1302.h 三、蓝桥杯实践 一、DS1302简介 RTC(Real Time Clock):实时时钟&#xff0c;是一种集成电路&#xff0c;通常称为时钟芯片。现在流行的串行时钟电路很多&#xff0c;如…

[java进阶]——方法引用改写Lambda表达式

&#x1f308;键盘敲烂&#xff0c;年薪30万&#x1f308; 目录 &#x1f4d5;概念介绍&#xff1a; ⭐方法引用的前提条件&#xff1a; 1.引用静态方法 2.引用构造方法 ①类的构造&#xff1a; ②数组的构造&#xff1a; 3.引用本类或父类的成员方法 ①本类&#xff1…

深入理解ClickHouse跳数索引

一、跳数索引​ 影响ClickHouse查询性能的因素很多。在大多数场景中&#xff0c;关键因素是ClickHouse在计算查询WHERE子句条件时是否可以使用主键。因此&#xff0c;选择适用于最常见查询模式的主键对于表的设计至关重要。 然而&#xff0c;无论如何仔细地调优主键&#xff…

深度图(Depth Map)

文章目录 深度图深度图是什么深度图的获取方式激光雷达或结构光等传感器的方法激光雷达RGB-D相机 双目或多目相机的视差信息计算深度采用深度学习模型估计深度 深度图的应用场景扩展阅读 深度图 深度图是什么 深度图&#xff08;depth map&#xff09;是一种灰度图像&#xf…

Windows 10 启用 Hyper-V

文章目录 Windows 10 启用 Hyper-V打开控制面板打开任务管理器 Windows 10 启用 Hyper-V 打开控制面板 打开程序和功能 启用或关闭Windows功能 立即重启 打开任务管理器 出现下图&#xff0c;代表已启用

医院pacs系统是什么?

医院pacs系统是什么&#xff1f; PACS系统的概念已从原来将数字化的医学影像通过网络传送到连接在网络上的影像显示工作站上作一般显示和进行数字化存储&#xff0c;发展成为以数字化诊断&#xff08;无纸化、无胶片化&#xff09;为核心的整个影像管理过程&#xff0c;包括&a…

2023/11/7 JAVA学习

ctrl alt t自动重写

Selenium爬取内容并存储至MySQL数据库

前面我通过一篇文章讲述了如何爬取博客摘要等信息。通常,在使用Selenium爬虫爬取数据后,需要存储在TXT文本中,但是这是很难进行数据处理和数据分析的。这篇文章主要讲述通过Selenium爬取我的个人博客信息,然后存储在数据库MySQL中,以便对数据进行分析,比如分析哪个时间段…

MAC设备(M1)环境下编译安装openCV for Java

最近发现一个需求&#xff0c;可以用openCV来实现&#xff0c;碰巧又新买了mac笔记本&#xff0c;就打算利用业余时间安装下openCV。这里将主要步骤记录下&#xff0c;希望能帮助有需要的人。 1、准备编译环境 #查询编译opencv相关依赖 brew info opencv查询结果如下图所示&a…

css排版—— 一篇优雅的文章(中英文) vs 聊天框的特别排版

文章 <div class"contentBox"><p>这是一篇范文——仅供测试使用</p><p>With the coming of national day, I have a one week holiday. I reallyexpect to it, because it want to have a short trip during these days. Iwill travel to Ji…

结合双向LSTM和注意力机制的DQN-CE算法船舶能量调度

Title:Ship Energy Scheduling with DQN-CE Algorithm Combining Bi-directional LSTM and Attention Mechanism 【Applied Energy】结合双向LSTM和注意力机制的DQN-CE算法船舶能量调度(中科院1区Top,IF 11.2) 具体实现方法可以参考原文:论文地址 欢迎大家引用和交流,具体…

如何在在线Excel文档中规范单元格输入

在日常的工作中&#xff0c;我们常常需要处理大量的数据。为了确保数据的准确性和可靠性。我们需要对输入的数据进行规范化和验证。其中一个重要的方面是规范单元格输入。而数据验证作为Excel中一种非常实用的功能&#xff0c;它可以帮助用户规范单元格的输入&#xff0c;从而提…