第3章Python的基本概念 本章主要介绍Python程序设计的基本概念。 本章的学习目标: 掌握Python源程序的结构,编码、标识符、注释(含docString)的使用; 掌握Python关键字、常见的内置函数、Python名字空间的概念; 掌握PYTHONPATH环境变量的配置与使用、Python 模块与包的使用。 3.1Python相关的文件 3.1.1Python的几种文件类型 Python系统软件既是一个Python程序开发环境,也是一个Python程序运行环境。Python系统有以下几种类型的文件。 (1) py: Python源代码文件。 (2) pyc: Python字节码文件。 (3) pyw: Python带用户界面的源代码文件。 (4) pyx: Python包源文件。 (5) pyo: Python优化后的字节码文件。 (6) pyd: Python的库文件(Python版DLL),在Linux上是so文件。 最常见的是*.py和*.pyc格式的Python程序文件。 3.1.2Python源程序示例 首先看一个Python源程序示例。该程序的功能是: 打印当前日期时间,调用函数hi()显示字符串"hello"+参数信息。 【例3.1】Python程序代码示例。 # -*- coding: utf-8 -*- 源文件编码格式声明 """ Created on Tue Feb 25 09:07:47 2020 @author: Administrator 注释信息 """ import datetime 引入外部模块(库) #获取当前时间 注释信息 t=datetime.datetime.now() 源代码 def hi(name): 定义 get_py()函数 """ Parameters ---------- f : list files and directories list 注释及帮助信息,可能用__doc__获取字符串内容 Returns ------- flpy : list list only contains python files. """ return 'hello:'+ str(name) 函数返回值 if __name__ == "__main__": 判断是否运行在主模块 print(t) print(hi('James')) 程序源代码 将上面的程序代码保存到c:\mycode\demo.py 文件。在操作系统提示符下输入 c:\python c:\mycode\demo.py,Python会自动在其所在的目录下创建_pycache_文件夹,并将demo.py编译,得到demo.cpython38.pyc字节码文件。程序运行结果: 2020-04-03 11:58:19.445626 hello:James 从上面的演示代码可以看出,一个Python程序通常由源码格式声明、注释、引入外部模块(库)、源代码、函数、类等语句组成。每条语句根据Python的语法规则构成,包含源码格式声明、注释、标识符、运算符、关键字、函数、类等。 3.1.3Python源程序编码格式 Python源程序是文本文件,默认为UTF8 编码。可以使用任何文本编辑器编写Python源程序。不同操作系统下对文本编码可能不同,如在Windows操作系统下的记事本可以选择ANSI、Unicode、Unicode big endian、UTF8类型的编码(见图3.1)。这就导致Python的源程序可能存在多种编码。 图3.1源程序的编码格式 如果源码文件使用非UTF8类型的编码,必须在Python源程序的第一行声明文件的编码格式。如: # -*- coding: cp-936 -*- 3.1.4Python源程序的注释与文档字符串 Python有单行和多行注释两种方式。Python程序的注释语句的作用主要是备注程序代码功能和逻辑关系、算法的编写思路,以便于程序的后期维护等。另外,符合规范的Python程序注释,可以自动生成对应的帮助文档。 (1) 单行注释。Python中单行注释以#开头。实例如下: 【例3.2】第一个注释。 #第一个注释 print ("Hello, Python!") (2) 多行注释。多行注释可以用多个 # 号或用成对的三个单引号 ''' 或三个双引号 """来标注。 例3.1所示的程序已经演示了单行注释与多行注释。 另外,Python语言引入了文档字符串(docString)机制。文档字符串是一种多行注释,它作为模块、函数、类或方法定义中的第一条注释语句出现。这样的文档字符串自动成为该函数或对象的特殊属性__doc__。 __doc__属性可以被Python程序访问,而且还可以直接由相关工具生成HTML等格式的文档。Python的PEP257(https://www.python.org/dev/peps/pep0257/)规定了文档字符串的标准格式。 【例3.3】查看__doc__属性。 通过代码: print(hi.__doc__) 或者在Python 提示符>>>下输入help(hi),均打印如下信息: Help on function hi in module __main__: hi(name) Parameters ---------- name : string a string,such as name Returns ------- flpy : string hello + string 3.1.5Python语言的代码块 Python语言的代码块是指具有一定逻辑功能的n行代码语句。Python使用相同的缩进空格来表示同一代码块。 (1) 缩进空格。缩进的空格数是可变的,但是同级别的一个代码块的语句必须包含相同的缩进空格数。通常采用 4个空格表示一个缩进。 【例3.4】Python语言代码块缩进代码示例。 if True: print ("True") else: print ("False") 如果同级别代码块缩进数的空格数不一致,会导致运行错误: if True: print ("Answer") print ("True") else: print ("Answer") print ("False")#缩进不一致,会导致运行错误 File "<tokenize>", line 6 print ("False") ^ IndentationError: unindent does not match any outer indentation level (2) 分行语句。Python 通常是一行写完一条语句,但如果语句很长,可以使用反斜杠(\)来实现将一行长的语句分成多行语句。 【例3.5】Python语言一行长代码换行写法代码示例。 total ="A33"\ "B44"\ "C55" print(total) 在[],{},或()中的多行语句,不需要使用反斜杠(\)。例如: total = ['item_one', 'item_two', 'item_three', 'item_four', 'item_five'] A33B44C55 3.2Python语言的关键字 Python语言的关键字是构造Python逻辑程序代码的核心要素,关键字类似英语中的“单词”,它与用户定义的变量或函数组合构成程序语句代码。 关键字可以按类别分为常量、逻辑运算、程序流控制、异常与上下文处理、函数相关、模块与类管理6大类(见图3.2)。 图3.2Python语言关键字分类 另外,有趣的是Python提供了一个 keyword 模块,使用两行Python程序代码可以输出当前Python版本的所有关键字。 【例3.6】查看当前Python版本所有关键字。 >>> import keyword >>> keyword.kwlist#关键字列表 >>>len(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'] 35 可以看到,Python共有35个关键字。有许多关键字与其他编程语言是相同的。如'assert', 'break', 'class', 'continue', 'else', 'except', 'finally', 'for', 'if', 'import', 'return', 'try', 'while'等与Java语言的关键字是相同的,而且含义和用法也是一样的。 提示: 程序员自定义自变量、函数不能与关键字相同,否则程序会报错。 3.3Python的标识符 Python语言中用户定义的变量、函数、类名、模块等是用标识符来表达的。标识符有比较严格的命名规则,这些规则为: (1) 标识符不能与关键字相同。 (2) 标识符的第一个字符必须是字母(ASCII码字符或 Unicode码字符)或下画线(_)。标识符对英文的大小写敏感。标识符的其他部分可以由字符、下画线、数字组成,标识符的长度没有限制。 可以使用非 ASCII码字符做标识符,如中文作为变量名或函数名。如_ko、“中国”、disk等是合法的标识符; 3ks、in、+wps等是不合法的标识符。 Python中的特殊标识符为下画线标识符。 Python 有其专用的下画线标识符,“_”(1个下画线)或 “__”(2个下画线)可作为变量标识符的前缀和后缀来标识特殊变量 。表3.1所示为Python中的下画线标识符。 表3.1Python中的下画线标识符 类型描述含义示例 _xxx 1个下画线开始保护变量,只有类对象自己和子类对象能访问到这些变量_foo __xxx 2个下画线开始私有成员,只有类对象自己能访问,连子类对象也不能访问__foo __xxx__2个下画线开头、结尾通常是Python系统定义的名字__init__()、__main__ 一般来讲,变量名_xxx 被看作是“私有的”,在模块或类外不可以使用。当变量是私有的时候,用_xxx 来表示变量是很好的习惯。 由于下画线对Python解释器有特殊的含义,建议初学者在不明确下画线的含义时,避免用下画线开头或结尾的标识符作为变量名。 3.4Python的内置常量 Python内置的名字空间中已经定义了6个常量(见图3.3)。 图3.3Python语言中的6个常量 (1) False: bool 类型的假值。 (2) True: bool 类型的真值。 (3) None: NoneType 类型的唯一值。None 经常用于表示缺少值。 (4) Ellipsis: 省略号文字,Python使用 “…”,主要与用户定义的容器数据类型的扩展切片语法结合使用。 (5) __debug__: 如果 Python 没有以 O 选项启动,则此常量为真值。 (6) NotImplemented: 二进制特殊方法应返回的特殊值(某些方法没有被实现,返回该错误)。 3.5Python的内置函数 Python语言核心部分内置了大约69个内置函数(也称内部函数)。在Python程序中,可以直接调用这些函数(https://docs.python.org/3.9/library/functions.html)。进入Python系统,在>>>提示符下,输入dir(__builtins__),就会显示Python内置空间中的函数名、常量和关键字。 Python语言内置函数可参看https://docs.python.org/3.9/library/functions.html。可以将Python内置函数分为数字相关、数学运算、编码相关、序列相关、对象相关、系统函数、输入输出和变量相关8个大类(见图3.4)。 图3.4Python语言内置函数及分类 提示: 避免使用与内置函数名相同的标识符(变量名、函数、类名等)。否则,内置函数会被用户定义的同名标识符覆盖。 在此,先介绍Python使用频率最高的几个内置的函数(见图3.5)。 图3.5常见内置函数 (1) 对象相关的常用内置函数。 id(object) 功能: 返回对象在内存中的地址。 dir(object) 功能: 查看对象的相关名字空间,返回该空间的对象列表。 type(object) 功能: 可以获取object对象的类型。 del object 功能: 删除object对象。 (2) 常用输入输出函数。 input([prompt]) 功能: 输入函数。显示提示信息,等待用户输入,返回输入字符串str。 print(*objects, sep=' ', end='\n', file=sys.stdout, flush=False) 功能: 输出函数。将对象objects打印到输出流。 3.6Python的名字空间 在Python程序中,变量、函数、类等都是通过标识符来定义的。每一个标识符都会在相关的名字空间(namespace)占据一定位置。Python会把命名后的变量、函数、类、对象分配到的相关的名字空间,并通过名称在相应名字空间中查找、使用它们。 Python名字空间有两个作用: (1) 区分不同作用域; (2) 防止同名变量、函数、类等名字冲突。 若Python同一个名字空间中出现同名变量、函数、类等,则出现的同名变量、函数、类将覆盖先前的。 查看名字空间的命令函数是dir()。 如,查看定义x=100前后Python名字空间内的变化情况。 【例3.7】查看名字空间。 定义变量前名字空间内的对象名称: >>> dir() ['__annotations__', '__builtins__', '__doc__', '__loader__', '__name__', '__package__', '__spec__'] 定义变量后名字空间内的对象名称: >>> x=100 >>> dir() ['__annotations__', '__builtins__', '__doc__', '__loader__', '__name__', '__package__', '__spec__', 'x'] 可以看到变量x已经占据了当前的名字空间的一个位置。 如果释放变量、函数、类等的名字空间,直接使用del加变量、函数、类模块名称。 【例3.8】del()函数案例。 清理、删除对象x: del x >>> dir() ['__annotations__', '__builtins__', '__doc__', '__loader__', '__name__', '__package__', '__spec__'] 可以看到运行了del x命令后,x所占据的名字空间已经释放。 【例3.9】定义一个函数后的名字空间。 >>> def s(length): x=300 y=400 >>> dir() ['__annotations__', '__builtins__', '__doc__', '__loader__', '__name__', '__package__', '__spec__', 's'] 图3.6Python的名字空 间及作用范围 如图3.6所示,Python有三个级别的名字空间,即局部、全局和内置名字空间。 (1) 局部名字空间。Python会把在函数内部声明的变量放置到局部名字空间,记录函数内部的变量、传入函数的参数、嵌套函数等被命名的对象。 (2) 全局名字空间。Python全局名字空间的变量其作用域为整个模块,记录模块x的变量、函数、类及其他导入的模块等被命名的对象。 (3) 内置名字空间。记录Python自身提供的内置函数、模块等被命名的对象。 可以使用globals()、locals()、vars()来查看全局、局部变量的使用情况。 【例3.10】查看变量的使用情况。 >>> globals() {'__name__': '__main__', '__doc__': None, '__package__': None, '__loader__': <class '_frozen_importlib.BuiltinImporter'>, '__spec__': None, '__annotations__': {}, '__builtins__': <module 'builtins' (built-in)>, 'x': 100, 's': <function s at 0x0000000000445160>} >>> locals() {'__name__': '__main__', '__doc__': None, '__package__': None, '__loader__': <class '_frozen_importlib.BuiltinImporter'>, '__spec__': None, '__annotations__': {}, '__builtins__': <module 'builtins' (built-in)>, 'x': 100, 's': <function s at 0x0000000000445160>} >>> vars() {'__name__': '__main__', '__doc__': None, '__package__': None, '__loader__': <class '_frozen_importlib.BuiltinImporter'>, '__spec__': None, '__annotations__': {}, '__builtins__': <module 'builtins' (built-in)>, 'x': 100, 's': <function s at 0x0000000000445160>} 在Python程序运行过程中,会有局部名字空间、全局名字空间和内建名字空间同时存在。Python对变量、函数、类的使用是按照“局部名字空间”→“全局名字空间”→“内置名字空间”的顺序查找的。如果找到了就使用,如果找不到,将放弃查找并引发一个 NameError 异常。 【例3.11】NameError异常举例。 >>> aa Traceback (most recent call last): File "<pyshell#3>", line 1, in <module> aa NameError: name 'aa' is not defined 3.7Python的模块 一个Python源程序,如例3.1中的c:\demo\demo.py,就是一个Python 模块。如果要在其他程序中使用demo.py模块,首先要 图3.7PYTHONPATH的配置 在环境变量PYTHONPATH中配置该模块的检索路径(见图3.7)。 然后,使用import demo命令,就可以使用demo.py模块中定义的函数、变量了。 【例3.12】导入模块。 >>> import demo >>> dir() ['__annotations__', '__builtins__', '__doc__', '__loader__', '__name__', '__package__', '__spec__', 'demo'] 【例3.13】查看demo名字空间。 >>> dir(demo) ['Info', '__builtins__', '__cached__', '__doc__', '__file__', '__loader__', '__name__', '__package__', '__spec__', 'datetime', 'hi', 't'] 调用demo名字空间下的函数,必须在前面加名字空间名称。 【例3.14】调用模块内函数示例。 >>> demo.hi('james') 'hello:james' >>> demo.Info() hello from Info <demo.Info object at 0x0000000002CA3F10> >>> 提示: import demo是将demo.py模块内的变量、函数导入 demo名字空间下,使用时要加上demo名字空间名。 另一种导入方式是将demo.py模块内的变量、函数导入全局名字空间内。可以使用 from demo import * 语句 直接调用函数名。 【例3.15】使用第二种导入方式调用函数示例。 >>> from demo import * >>> dir() ['Info', '__annotations__', '__builtins__', '__doc__', '__loader__', '__name__', '__package__', '__spec__', 'datetime', 'hi', 't'] >>> hi('james') 'hello:james' 提示: from demo import *是将demo模块内的变量、函数或类等导入全局名字空间内,可以直接使用相关函数。 3.8Python的包 Python中的包(Package)是组织、管理源代码的一种方式。包就是一个容器,用来存放其他模块和子包。如,一个大的Python项目可能由不同开发人员分工完成,使用包来组织代码、管理代码可以避免出现模块名、变量名、函数名、类名等重名的问题。 图3.8Python中树 状目录结构 Python的包使用树状目录结构组织模块(见图3.8),将Python代码按照不同级别的目录存放,每个目录下面必须有个__init__.py文件(文件内容可以为空),代表该目录下的Python文件使用包进行管理。 可以简单地把包理解为按照不同级别的子目录来组织模块代码,每个目录下必须有一个__init__.py文件。包的本质就是一个含有__init__.py文件的文件夹。 使用Python包中的模块语法是通过目录的级别的方式来引用模块(如PackageA.PackageB)。 PackageB、PackageC目录下均有同名m1.py,m2.py 模块。这可以通过包名和模块名来区别的。如: import Package.APackageB.m1 import Package.APackageC.m1 提示: Python会在sys.path 指定的目录(环境变量 PYTHONPATH 所指定的目录)下搜索包的路径。 包中的模块和函数,可以通过两种导入方式使用。 (1) import包的名字。 (2) from包的名字import函数名。 Python系统用import导入包,会创建一个包的名字空间,包的名字来自__init__.py。 3.9本章小结 图3.9所示为本章知识要点一览图。本章主要介绍了Python源程序的结构,编码、标识符、注释、Python关键字、几个常见的内置函数、Python模块和包。 图3.9本章知识要点一览图 扫码观看 3.10习题 (1) 编写一个打印字符串变量s="hello"的程序h.py。 (2) 利用Python的包管理机制,将h.py放在 a.b包下,并利用import a.b.h, 输出s的内容。