如何写出中高级程序员的代码?

290 阅读7分钟

最近一直在强调代码规范,但是有很多朋友不太清楚,我到底要怎么抒写代码,才算是规范呢?

那什么是代码规范呢?代码规范也就是指在编写代码时,我们需要去遵循一些通用的编写方式或编写风格。注意,并不做强制性(也就是说不按规范写并不会报错),但是却是《程序员自我修养》的必学之技。开始肝!

那今天主要来聊聊 Python 编码风格指南——PEP 8

PEP8介绍

PEP 8 的英文全称为 Style Guide for Python Code ,即 Python 编码风格规范,主要涵盖三个大的方面

  • 命名规范
  • 注释文档
  • 代码布局

命令规范

命名规范是我们一直在强调的,那实际上它是一个非常具有扩展性的话题,我们需要了解 主要的命令规则 以及 python 中针对 不同元素 的常用命名方式。

常见命名规则

  • 小驼峰命名法:以一至多个逻辑单元构成,每个逻辑单元都可称为一个识别字,每个识别字首字母小写,其余识别字首字母大写,比如:oldKing
  • 大驼峰命名法:与小驼峰命名法类似,区别为首字母大写。比如OldKing
  • 下划线命名法:和驼峰命名法类似,区别为所有识别字均小写,识别字之间使用_连接,比如old_king

除此之外,还有其他形式的命名规则,比如大写 OLDKING、大写结合下划线OLD_KING、小写oldking等。另外在Python中也有 前缀 或者 后缀 下划线、双下划线等命名方式。

Python常用的命名方式

对于变量与常量:

  • 变量名 可 小写,也可使用 下划线命名;
  • 常量 应使用 全大写字母,必要时使用 下划线分隔,并且要注意在Python中并没有类似其他语言中const的概念,常量 仅仅是一种 约定(常量通常放置在代码顶部、或单独的模块、或特定的配置文件中)。
  • 对于 容器类变量 ,常采用 复数 名词形式;对于 映射类变量 ,常采用key_value的形式,其中key、value为键和值的实际含义。比如:information_value = {"name":"amy","age":18}
  • 对于表示 布尔值 的变量或者常量(但不仅限于这两者),常采用has、is作为前缀。

对于类(和异常):

  • 类名 应使用大驼峰命名(这里不包括一些Python内置的类,比如int、list),类和属性常采用名词,方法多采用动词或者包含动词。
  • 基类 常采用Base作为前缀,抽象类 常采用 Abstract 作为前缀。
  • 异常名 应使用大驼峰命名法,当此异常表示一个错误时,应添加Error后缀(并不是所有异常都代表代码运行错误,比如 KeyboardInterrupt、SystemExit )。

对于函数、方法:

  • 函数名、方法 名应使用 小写,也可使用 下划线命名(但我们仍会在一些代码中看到一些方法或者函数名称采用了驼峰命名法,甚至在Python的标准库中也存在这样的现象,比如在 threading 模块中,因为这些代码的出现往往早于 PEP 8 规范的诞生,同时为了向后兼容而保留,但通常这些模块都会提供相同功能的以小写加下划线命名的方法,我们应该尽可能使用这些新的方法)。
  • 实例方法 的首个参数名应为self,类方法的首个参数应为cls( class作为关键字不能被使用,常被cls klass替换);

对于模块和包:

  • 模块(modules) 名应尽可能使用 小写,在必要时可以使用下划线命名(除了 __init__ 模块以外)
  • 包(packages) 名应使用 小写,最好不要使用下划线;

特殊格式:

  • 单下划线前缀,比如_name ,常称为 ”伪私有属性“(也可用于私有的方法、类等),这种命名方式在 Python 中是一种表示私有属性的约定(同时注意from ... import *时不会导入这种形式的对象,并且这种伪私有变量通常会通过特定的方法来获取或者赋值),私有属性通常没有直接对外的功能,常用于记录内部状态或用于提供一些公共功能的方法内使用;

单下划线后缀,比如 name_ ,常用于 避免 和 Python 的 关键字 发生冲突;

双下划线前缀,比如 __name,常用于 基类避免 和 子类中的命名冲突,Python 会通过转换规则将其转换为类似_Class__name 的形式,这种方式通常称为命名修饰name manglingname decoration(这种方式通常用于多继承,应避免将这种形式用在私有属性的命名上);

>>> class MyClass:
...     __name = 1
...
>>> MyClass.__name  # 无法直接访问
Traceback (most recent call last):
  File "<input>", line 1, in <module>
AttributeError: type object 'MyClass' has no attribute '__name'
>>> MyClass._MyClass__name
1

前后双下划线,比如__name__,这是我们之前提到过的Python内部常用的dunder名称,不应自定义这类命名。

注释编写

注释对于代码的阅读、扩展以及维护都非常重要。在 Python 中常用的注释方式有三种,分别为块注释(Block Comments)、行内注释(Inline Comments)、文档字符串(Documentation Strings)。

块注释(Block Comments

块注释 在代码内部比较常见,其通常由一至多个段落构成,段落之间应使用开头为 # 的空行隔开,每个段落由完整的句子构成,在每行以 # 和一个空格开始。另外,块注释和被注释代码之间应具有同级别的缩进,这样有助于区分注释和代码之间关联关系。如下代码体现出块注释:

@classmethod
def fromkeys(cls, iterable, v=None):
    # There is no equivalent method for counters because the semantics
    # would be ambiguous in cases such as Counter.fromkeys('aaabbc', v=2).
    # Initializing counters to zero values isn't necessary because zero
    # is already the default value for counter lookups.  Initializing
    # to one is easily accomplished with Counter(set(iterable)).  For
    # more exotic cases, create a dictionary first using a dictionary
    # comprehension or dict.fromkeys().
    raise NotImplementedError(
        'Counter.fromkeys() is undefined.  Use Counter(iterable) instead.')

行内注释( Inline Comments

行内注释 是一种形式相对简单的注释,它和表达式或语句位于同一行,之间应通常使用两个空格隔开,注释部分应以 # 和一个空格开始。

one_list = []  # 创建列表

文档字符串( Documentation Strings )

在 Python 中,最重要的注释形式便是 文档字符串。主要用于两方面:

用来对模块、类、函数、方法等进行说明;

可以配合一些辅助工具来自动化生成代码文档

当然大家现在可能很难体会到文档字符串的重要性,但是提到开源这个词,我们就会知道,一个开源文档的质量取决于它的可读性,而可读性往往伴随着大量的说明文档。

def function_name():
    """docstrings"""
    pass

代码布局

缩进与空格

Python 在语法上使用 缩进 来确定代码块的开始和结束,对于每一级缩进,都应该是 4个空格。当然,在 Pycharm 当中,我们可以设置使用 tab 键来进行缩进。

那需要注意,缩进本身是 强制性的,但是空格数量实际上语法并没有做限制。只不过同级代码缩进空格一致即可。

当然,一般我们都是以 4个空格 来进行使用。

# 4个空格表示缩进
def function_name():
    """docstrings"""
    pass


# 8个空格表示缩进
def function_name_two():
        """docstrings"""
        pass

代码之间的空行

函数与类之间应该使用两个空行隔开,而类的内部的方法之间应该使用一个空行隔开,函数或方法中不同功能的代码块可使用空行隔开。

观察以下代码空行规则:

class MyClass(object):
    def method_one(self):
        pass
    
    def method_two(self):
        pass


def function_name():
    """docstrings"""
    pass


def function_name_two():
    """docstrings"""
    pass

常用的我们就讲解到此,大家在写代码的时候一定要注意代码规范!这样才会增加我们代码的可读性,显得更加专业。