No.3 Python模块结构和布局

在了解了Python的数据类型和语法结构之后,对于如何将这些数据类型及语法结构组织成一个完整的程序,可能并没有清晰的概念。

此篇将带你了解,如何将各种数据类型及语法结构,组合成一个完整的Python程序。

1、语句和语法

1.1 注释(#)

尽管Python是可读性最好的编程语言之一,但并不意味着我们在开发程序的过程中,完全忽略注释。

在实际开发过程中,需要注意以下几点

a. 不需要对代码进行逐行注释,对于大部分一目了然的代码而言,并不需要添加注释;

b. 对于比较复杂的单行代码,应该在该行代码后进行相应的注释;

c. 对于一系列相对复杂的代码,应在此系列代码前,进行注释说明;

d. 注释内容无需对代码进行解释,只需说明其用途即可。

1.2 继续(\)

根据Python的PEP8编码规范,单行代码的长度每行不应超过79个字符。

然而在实际开发过程中,经常会遇到单行代码过长的情况,例如条件判断语句或包含长字符串的语句,此时需要我们用的拆行符(\)对代码进行拆分。

1.3 代码组

缩进相同的一组语句构成一个代码块,我们称之为代码组。代码组可能是一行或多行代码。

代码组由不同的缩进分割,同一代码组应严格执行左对齐(缩进一致),如不遵守此规则,则代码可能出现语法错误无法运行。

1.4 模块

之前我们提到,任意一个以 .py 结尾的文件都可以被当做是一个模块。

当我们自定义一些模块时,可以根据模块的作用对不同功能的代码进行分类,单个模块中的代码,应尽可能是一类对象,方便后期的维护及使用。

模块名的定义,应尽可能与内容一致,最好做到见名(模块名)知意(模块作用)。

应适当控制模块中的代码长度,当功能太多时,可以考虑进行拆分,避免单个文件过大。

2、变量赋值

2.1 赋值运算符

Python语言中,等号(=)是主要的赋值运算符,再此基础上,还可以拓展出其他赋值运算符。

在使用过程之,赋值运算符用于将右侧的值传递给左侧的变量,右侧的值可以是具体的值,也可以是经过某些运算后的结果。

2.2 增量赋值

当我们想要对变量进行增量计算时,除了常规的做加法计算赋值外,还可以对此进行简写,如下:

 # 增量赋值
 x = 1
 x = x + 1
 ​
 # 增量赋值简写
 y = 1
 y += 1

除此之外,其他运算符也可与赋值运算符进行组合简写,如下:

 # 减法赋值
 m = 100
 m -= 1
 ​
 # 乘法赋值
 n = 2
 n *= 2
 ​
 # 除法赋值
 p = 4
 p /= 2
 ​
 # 乘方赋值
 q = 3
 q **= 3

2.3 多重赋值&多元赋值

多重赋值:同时将一个对象赋值给多个变量。

多元赋值:同时将多个对象赋值给多个变量。

 # 多重赋值
 a, b, c = 123
 ​
 # 多元赋值
 x, y, z = 1, 2, 3

2.4 其他赋值

除了以上赋值方法外,还有一些其他的方法,可以根据需要,灵活使用。

 # 交换赋值
 x, y = 1, 2
 x, y = y, x
 ​
 # 解压赋值
 aList = [1, 2, 3]
 a, b, c = aList
 ​
 aTuple = (4, 5, 6)
 x, y, z = aTuple

3、标识符

Python的标识符通常用于变量、函数‘类、模块等的名称。

3.1 标识符命名规则

a. 第一个字符必须是字母或下划线(_)

b. 剩下的字符可以是字母和数字或下划线

c. 大小写敏感

3.2 关键字

即Python预定义的保留标识符。随着Python语言版本的更新迭代,有可能会发生变化,可通过函数调用,随时查看当前版本中具体关键字信息

 >>> import keyword
 >>> keyword.kwlist
 ['False', 'None', 'True', 'and', 'as', 'assert', 'async', 'await', 'break', 'class', 'continue', 'def', 'del', 'elif', 'else', 'except', 'finally', 'for', 'from', 'global', 'if', 'import', 'in',  'is', 'lambda', 'nonlocal', 'not', 'or', 'pass', 'raise', 'return', 'try', 'while', 'with', 'yield']

3.3 专用下划线标识符

通常,Python用下划线作为标识符前缀或后缀时,表明该变量具有特殊含义。具体如下:

3.3.1. 单下划线开头的标识符

protected标识符,可理解为保护标识符,只可被类以及其子类访问到。如果你写了一个方法只希望在类中被调用,不希望外部调用,可在该方法前加上下划线,告诉解释器这是一个protected标识符。

3.3.2 双下划线开头的标识符

private标识符,可理解为私有变量,只可以被该标识符所在类访问到,子类都不行。

3.3.3双下划线开头双下划线结尾标识符

python中的特殊方法标识符。这类标识符在python中往往具有特殊含义,python中的魔法方法就是这种标识符,如__init__。我们自己自定义标识符应该尽量避免使用这类标识符。

4、基本风格指南

4.1 编码规范

每种编程语言都有其指定的编码规范,而PEP8就是官方指定的Python编码规范。

有兴趣的小伙伴可以前往官网进行查阅。

PEP 8 – Python 代码|风格指南peps.python.org

4.2 模块结构和布局

 # (1) 起始行
 # (2) 模块文档                       
 # (3) 模块导入
 # (4) 变量定义
 # (5) 类定义
 # (6) 函数定义
 # (7) 主程序

4.2.1 起始行

通常,在linux系统中,需要在文件首行注释Python解析器路径,其目的就是告诉操作系统在执行这个文件的时候,调用该路径下的Python解释器。

windows系统通常无需说明,可在文件属性中修改打开方式,即可直接运行此python程序。

4.2.2 模块文档

模块文档主要目的是说明当前模块的主要功能及全局变量的含义等,也可根据实际需要,适当添加需要的信息。

4.2.3 模块导入

导入当前模块代码所需的其他模块,没个模块只需导入一次即可;

模块导入应尽可能精简,无需导入过多用不到的模块方法。

4.2.4 变量定义

此处定义的变量,通常成为全局变量,可供模块中所有的函数直接使用。

实际开发过程中,非必须,应尽可能使用局部变量,方便代码的后期维护。

4.2.5 类定义

通过class关键字,可以再此定义模块中的类。

类方法是面向对象开发的关键,python中的类是指具有相同属性和方法的对象的集合,而对象则是指类的实例。

类是抽象的,而实例是具体的。比如人这个概念是抽象的,当我们对这个概念进行实例化之后,则可以具体为张三、李四等,每一个具体的对象都会继承人这个类的一些属性和方法,但却又包含一些各自的属性和方法。

4.2.6 函数定义

通过def关键字,可以在此定义模块中的函数。

当该函数被其他函数或主程序进行调用是,会执行函数内部具体的流程。

4.2.7 主程序

主程序可以理解为当前模块的程序入口,只要此模块被其他模块调用或被直接执行,都会执行这部分代码。

主程序中的代码,通常都是对已定义类、函数的调用,不做功能性代码的实现。

5、内存管理

5.1 变量定义

大多数编程语言,变量在使用前,需先声明变量的名字及类型。

不同于大部分编程语言,Python无需此操作,在第一次赋值之后自动声明,之后便可直接使用。

5.2 动态类型

变量赋值时,无需声明变量类型,解释器会根据赋值的对象,自动判断该变量的类型。

5.3 内存分配

我们知道,每一个对象的背后,都会借用一定的系统资源,在使用过后,我们也应该归还这部分系统资源。

在我们实际开发过程中,并不需要关心这些底层的问题,因为Python解释器会自动的帮我们完成内存管理的任务,我们只需要关注代码本身的逻辑即可。

5.4 引用计数

在Python内部,记录着所有使用中的对象各有多少个引用,以此来追踪内存中的对象。

当这个对象被创建并赋值给变量时,引用计数为1;

每当这个对象被赋值给其他变量或当做参数传递给函数、方法或者类实例时,引用计数+1;

当对象的引用被销毁时,即变量被赋值给一个新的对象时、使用该参数的函数或方法运行结束或者手动删除(del语句)一个变量时,该对象的引用计数-1;

当对象的引用计数为0时,回自动被程序回收。

5.5 垃圾收集

当一个对象的引用书为0时,Python的垃圾收集器会自动的寻找该对象,并释放该对象所占用的内存。

大部分情况下,垃圾收集器不仅可以自动释放引用计数为0的对象,也可以对引用计数大于0,但也应该被销毁的对象,但特殊情况下,仍会出现对象无法被及时回收的情况。

对于一个长期运行的后台服务进程来说,如果内存持续增长,则可能出现了内存泄漏的情况,此时需要我们使用工具及时找到这些异常的对象,并进行处理。

6、第一个Python程序

熟悉了以上内容,我们开始尝试第一个Python程序的开发。无需顾虑是否对Python足够了解,书读百遍,不如动手实践。

下边我们将开发一个记事本模块,通过输入文件名和文件内容,自动生成对应的文本文件。

6.1新建文件,输入代码

(notepad.py),并输入以下代码并保存

 """
 记事本
 """
 ​
 ​
 class NotePad(object):
     def __init__(self):
         self.file_path = None
 ​
     def get_file_name(self):
         """
         获取文件名
         :return:
         """
         name = input("请输入文件名:")
         self.file_path = f"{name}.txt"
 ​
     def write_content(self):
         """
         输入内容并保存
         :return:
         """
         content = input("请输入:")
         with open(self.file_path, "w", encoding="UTF-8") as f:
             f.write(content)
 ​
     def run(self):
         self.get_file_name()
         self.write_content()
 ​
 ​
 if __name__ == '__main__':
     notepad = NotePad()
     notepad.run()

起始行:此模块在Windows环境下开发,可忽略起始行

模块文档:1~3行,说明此模块功能为记事本

模块导入:此模块无需导入其他模块

变量定义:大多数情况下,均无全局变量的定义

类定义:6~29行,定义一个类(Notepad),初始化记事本文件路径为空,并提供了三个方法,分别为获取文件名称(get_file_name)、输入内容并保存(write_content),启动方法(run)

函数定义:类中已包含了我们需要的所有方法,无需额外定义其他函数

主程序:32~34行,此模块的启动入口,实例化(NotePad)类,并运行此实例对象。

6.2 运行文件

相信你已经在电脑中安装好了Python环境,打开cmd窗口,并将路径切换至py文件所在目录,输入python notepad.py 回车,程序即可运行

6.3 运行报错

很不幸,第一个程序运行报错了,不要慌,根据提示,是因为编码问题导致的,回头看我们所写的代码,因为代码中存在中文字符,导致Python解释器无法识别

PEP 263 – Defining Python Source Code Encodings | peps.python.org

这就涉及了另一个编码规范 PEP263,感兴趣的可以参阅一下,这里我们不详细赘述,我们只需要在模块的第一行输入 # -- coding: gbk -- 即可

修改完成后我们再此运行试一下

6.4 运行成功

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值