在了解了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 运行成功