关于 Python 系列其他文章的传送门
-
《 Python 基础语法 》 您当前所在位置

一、初识 Python¶
python 程序和 java 一样,编译后的二进制程序是运行在虚拟机中 pvm,而虚拟机的是用 C 开发的。
CPython: 原始、标准的实现方式;
JYthon: 用于与 Java 语言集成的实现;
IronPython: 用于与 .NET 集成实现。
Python 程序的执行:

python34-devel: 编译时用到的文件;
python34-lib: python3 的标准库;
python34-tools: 工具。
1 | yum install python34 python34-devel python34-libs python34-tools |
1 | ~]# python3.4 |
Python 的特点¶
Python 是动态类型的编程语言,一切皆对象。变量名是在 Python 的内存中单独存放的,而变量值也存在内存中。变量名会通过指针指向变量值,变量值可以被赋值用来保存数据。动态类型指的就是在运行的过程中,可以按需修改变量名对变量值的引用。
所以 a 和 b 如果值都为 15,那么可能这两个变量名引用的是同一个变量值,如果此时通过 a 修改为 30,那么 b 看到的也是 30。
变量名没有类型,可以随时指向不同的数据对象。只有变量值本身才有类型。
程序都是指令+数据组成:
- 过程式编程:以指令为中心,数据服务于指令需要;
- 先选择路线,再填充需要交通工具;
- 对象式编程:以数据(对象)为中心,指令服务于数据。先定义跟多类,然后通过对类中的属性赋值并实例化出来,而把类实例化的过程被称之为创建对象的过程;更适合编写大段代码;
- 先选择好要使用的交通工具,再决定路线;
Python 能够完整支持上面的两种思路,并可以将两者结合起来。
1 | >> a=123 |
核心数据类型,支持:
- 数值:
- 字符串:
- 列表:
- 字典:
- 元组:
- 文件:
- 其他类型:集合、类类型、Node、布尔型
数值类型:
- 整数
- 浮点数
- 复数
字符类型:
- 字符串:由特定顺序的字符所组成的字符序列:
- 和数值一样属于不可变对象;
- 支持使用
‘’、“”赋值,并且支持使用‘’‘或“”“来赋值一段数据,也就是数据可以换行;
1 | # 字符串可以做乘法 |
Python 程序文件¶
将编写的程序保存至以 .py 结尾的文件中,方便多次运行。
- 在 Python 中,这类包含了一系列预编写好的语句的程序文件称为模块;
- 能够直接运行的模块文件通常被称作脚本(即程序的顶层文件)
示例:
1 | #!/usr/bin/python3.4 |
运行时会创建一个编译文件 .pyc,为了加快速度,被调用模块的编译文件不会被删除,而顶层文件的编译文件在执行完后会被删除。
Python 程序可以分解成模块、语句、表达式和对象:
- 程序有模块构成;
- 模块包含语句;
- 语句包含表达式;
- 表达式建立并处理对象;
- 表达式是“某事”,而语句是“做某事(即指令)”
- 例如:
3+4是某事,而print 3+4是做某事;
- 例如:
- 语句的特性:它们改变了事物,例如复制语句改变了变量,print 语句改变了屏幕输出等。
- 表达式是“某事”,而语句是“做某事(即指令)”
二、过程式编程¶
数据结构¶
Python 中最基本的数据结构就是序列。
序列中的每个元素被分配一个序号,即元素的位置,也称为索引:
- 从 0 开始编号,从左至右;
- 从 -1 开始编号,从右至左。
Python 中包含 6 种内键的数据序列:列表、元祖、字符串、Unicode 字符串,buffe 对象和 xrange 对象。
数据类型¶
基本数据类型:
- 整数;
- 浮点;
- 字符串:必须使用引号。
组合数据类型;
- 序列:
- 列表:
[]; - 元组:
(); - 字符串:
";
- 列表:
- 整合;
- 映射。
使用序号引用:
1 | l1 = ["mon","tue","wed"] |
多维引用:
1 | l2 = [["red","yello","balck"],["mon","tue","wed"]] |
列表中可以有不同类型的元素:
1 | l3 = [123,"abc"] |
逻辑操作符¶
Python 提供了4组逻辑运算:
- 身份操作符:
is:判定左端对象引用是否相同于右端对象引用;
- 比较操作符:
<,>,<=,>=,!=,==;
- 成员操作符:
in或not in:测试成员关系;
- 逻辑运算符:
and,or,not;
控制流语句¶
if
while
for…in
try
算数操作符¶
除了常见的算数操作集,很多 Python 数据类型也可以使用增强的赋值操作符,如 +=,-= 等。
通用的功能,使用增强型赋值操作符的性能较好。
int 类型是不可变的,所以增强型赋值实际的过程是创建了一个新的对象来存储结果后,将变量名执行了重新绑定。
输入输出¶
输出:print()
输入:input()
在 sys 模块中提供了 3 中标准文件对象:
- 标准输入:
sys.stdin; - 标准输出:
sys.stdout; - 标准错误:
sys.stderr;
三、函数的创建与调用¶
使用 def 语句定义函数;
1 | def functionName(arg): |
如果函数没被调用则不会运行函数的主体语句,但是会运行定义函数的 def 语句。
检测函数是否可被调用:
1 | callcable(a) |
Python 内置函数¶
Python 的标准库有众多的内置模块,这些模块拥有大量的函数。
- Python 模块实际上就是包含 Python 代码的
.py文件,其拥有自定义的函数与类,以及变量; - 导入模块使用
import语句进行,后面跟模块名称; - 导入一个模块后,可以访问其内部包含的任意函数、类、变量等。
导入一个随机数模块的示例:
1 | >> import random |
语句和语法¶
- 注释:
#; - 续行:
\; - 闭合操作符,单一语句跨行:
'''; - 代码组:
- 缩进相同的一组语句构成一个代码块;
- 首行以关键字开始,如
if、while等,以冒号结束; - Python 使用缩进来分割代码组,同一代码组的代码行必须严格左对齐,否则会造成语法错误。
- 同一行可以放置多个语句,使用
;分隔;
主程序¶
无论当前模块是被别的模块导入还是作为脚本直接执行,都会执行这部分代码。
- 最高级别的语句(没有缩进的),在模块被导入时就会执行,无论是否真的需要执行。因此:
- 仅在主程序模块中编写大量的顶级可执行代码;
- 用于被导入的模块只应该存在较少的顶级执行代码。
序列切片¶
1 | print(l1) |
字典¶
由多个键值对组成的集合就叫做字典。
在引用已有序列时是使用索引,而引用已有字典是使用键。
1 | d1 = {'name': 'Jerry', 'age': 18, 'title': 'UFO'} |
字典也是可变对象,可以被重新赋值,内部是新建了一个值并重新引用:
1 | d1['age'] |
其他操作:
1 | # 列出所有键 |
集合¶
通常被拿来做交叉并补运算。
1 | >> s1 = set('hello') |
深复制、浅复制¶
列表、字典、元组可以在不使用续行符的情况下位于多行上,因为他们有开闭两个符号。
每一个对象都有引用计数器,每次新做一次赋值时,引用的次数都会增加。如果引用的次数为 0 就会被垃圾收集器自动回收。
因为列表和字典是可变的,所以有两种复制方式,浅复制和深复制:
- 浅复制:两个元素引用同一个对象,当对象改变时两个元素都受影响;
l1 = a,l2 = l1; - 深复制:两个元素引用不同的对象;深复制需要使用
copy.deepcopy()模块;
每个对象都有一个唯一的身份标识,也就是内存地址,查看方式:
1 | id(l1) |
浅复制的内存地址是一样的。
is 比较¶
l1 == l2:对象值的比较;l1 is l2:是否为同一对象;type(l1) is type(l2):两个对象的类型是否相同。
四、Python 中的比较操作¶
Python 中不同类型的比较方法¶
- 数字:通过相对大小进行比较;
- 字符串:按照字典次序逐字符进行比较;
- 列表和元组:自左至右比较各部分内容;
- 字典:对排序之后的(键、值)列表进行比较;
Python 中真和假的含义¶
- 非零数字为真,否则为假;
- 非空对象为真,否则为假;
- None 则始终为假。
if 语法示例¶
基本:
1 | if l1 is l3: |
三元语法表达式:
1 | a=12 |
while 语法示例¶
在 Python 中的 while 可选择使用 else 分支,只要循环条件为假时并且循环是正常终止的,就会执行 else:
1 | sum = 0 |
- break:跳出所处的最近层循环;
- continue:跳到所处的最近层循环的开始处;
- pass:占位语句,当语法需要语句但还没有任何实用语句可写时使用。
for 循环语法格式¶
1 | for EXPRESSION1 in ITERABLE: |
通常 EXPRESSION 是一个单独的变量,或是一个变量序列,一般以元组的形式给出。
如果以元组或列表用于 EXPRESSION,则其中的每个数据项都会拆分到表达式的项,例如:
1 | t=[(1,2),(3,4),(5,6),(7,8)] |
注意:for 循环比 while 循环执行速度更快。
range¶
语法:
1 | range(stop) |
Python 3 提供一个内置函数(Python 2 是两个),用于在 for 循环中定制特殊的循环:
range:一次性地返回连续的整数列表;
1 | for i in range(4): |
zip¶
取得一个或多个序列为参数,将给定序列中的并排元素配成元组,返回这些元组的列表:
1 | L1 = [1,2,3,4,5,6,7] |
五、Python 迭代器和列表解析¶
迭代¶
迭代:支持每次返回自己所包含的一个成员对象。
可迭代对象:
- 序列:list、srt、tuple;
- 非序列:dict、file
迭代器¶
迭代器(iterator)又称游标(cursor),她是可以在一个容器物件(如列表)上实现元素遍历的借口。
使用 iter() 命令可从任何序列对象中得到迭代器:
1 | l1 = ['h','e','l','l','o'] # 创建一个列表 |
列表解析¶
列表解析就是根据一个表达式生成一个列表。
表达式的示例,含义:给 l5 映射一个从 0 到 50 的所有偶数列表:
1 | l5 |
表达式含义:从 0 到 10 所有数的平方为列表,映射给 l6:
1 | l6 = [ x**2 for x in range(10)] |
表达式含义:把从 0 到 10 的所有数对 2 取模,结果为 1 的数为列表,映射给 l7:
1 | l7 = [ x for x in range(10) if x%2 == 1 ] |
生成器¶
生成器表达式并不真正创建数字列表,而是返回一个生成器对象,此对象在每次计算出一个条目后,把这个条目“产生”出来。
- 生成器表达式使用了“惰性计算”或称作“延迟求值”的机制。
当序列过长,并且每只只需要获取一个元素时,应当考虑使用生成器表达式而不是列表解析,以节省内存。
- 生成器表达式于 Python 2.4 引入;
语法:
1 | (expr for iter_var in iterable) |
示例,一次只返回一个数,不像列表解析那样一次性全部显示:
1 | l8 = ( x for x in range(10) if x%2 == 1 ) |
- 列表解析使用:
[ ]; - 生成器使用:
( );
六、文件¶
使用 open() 可以创建一个文件对象。访问模式:
r:只读;w:覆盖写;a:追加;+:可读可写;b:二进制格式;t:文本格式,默认。
缓冲:
0:禁用缓冲;1:只缓冲一行;2:数字是几则为缓冲几行。
文件方法:
f1.close():关闭文件;f1.fileno():返回文件的描述符;f1.flush():把缓冲的数据刷写到磁盘中;f1.isatty():判断 f1 是否为 tty 设备;f1.next():一次返回一行;f1.seek(offset,whence=0):在文件中移动文件指针。含义:从whence指定的位置开始,偏移offset个字节;whence的取值:0:文件头;- 移动到文件头部:
f1.seek(0,0)
- 移动到文件头部:
1:当前位置;2:文件尾;
f1.tell():显示当前指针在第几个字节;f1.write():向文件写入数据;f1.writelines():向文件写入字符串序列。f1.read():读一个文件的指定字节数;
读取一个文件的示例:
1 | ~]# cp /etc/fstab /tmp |
使用覆盖写的方式创建一个文件的示例:
1 | srt1 = 'hellp fatab' |
os 模块¶
Python 对 IO 的访问主要通过 os 这个模块:
1 | import os |
os 中有很多子模块,比如 os.path,主要负责对路径操作。
os 模块的文件处理:
mkfifo()/mknod():创建命名管道文件/创建设备文件;remove():删除文件;rename():重命名;unlink():删除链接文件;stat():获取文件状态信息;symline():创建符号链接;utime:更新文件时间戳;tmpfile():创建并打开一个临时文件;walk():类似tree命令,生成一个目录下的所有文件名和目录名;chdir:同cd命令;chroot():同chroot命令;listdir():同ls命令;getcwd():同pwd命令;mkdir/makedirs:同mkdir命令;rmdir/removedirs():同rmdir命令:access():判断访问权限;chmod():同chmod命令;chown():同chown命令;umask():设置文件的mask;open():同rmdir命令;read()/write():同rmdir命令;
os.path 模块的路径处理:
basename():级名;dirname():路径名:getatime():获取文件的访问时间;getmtime():获取文件的修改时间;getctime():获取文件的创建时间;exists():判断文件是否存在;isabs():判断是否为绝对路径;isdir():判断是否为目录;isfile():判断是否为文件;islink():判断是否为链接;ismount():判断是否为挂载点;samefile():判断两个文件是否指向同一个文件;
持久存储¶
数据如果想要持久存储,需要存在磁盘中。而内存中的数据需要经过数据序列化后保存到磁盘上,以后才能正确的把数据原样的组合起来,也称之为数据扁平化。
七、Python 函数¶
在 Python 中有 4 中函数:
- 全局函数:定义在模块中;
- 局部函数:嵌套于其他函数中;
- lambda 函数:表达式;
- 方法:与特定数据类型关联的函数,并且只能与数据类型关联一起使用。
定义函数语法:
1 | def functionName(parameters): |
Python 脚本在运行到函数代码时,只会运行 def 这一行语句把函数对象创建出来,而不会真的执行函数体;
def 创建了一个对象并将其赋值给一个变量名(即函数名);
return 用于返回结果对象,其为可选;当无 return 语句的函数会自动返回 None 对象;
def 语句在运行之后,可以在程序中通过函数后附加括号进行调用,并可以在括号内传递参数。
名称空间¶
Python 中有名称空间的概念,创建、改变或查找变量名都是在名称空间中进行的。
在代码中变量名被赋值的位置决定了其全局的作用域。
函数定义了本地作用域,模块定义了全局作用域。
每一个模块是一个文件,是一个全局作用域,全局作用域的范围仅限于单个程序文件,在模块内可以直接用变量名来引用。但当模块被引用时,则要使用模块名+变量名才能使用。比如在 copy 模块中有一个变量 a,当在本模块中可以直接通过 a 来引用,但是在其他地方使用这个模块时,则要使用 copy.a 来引用变量。
每次对函数的调用都对创建一个新的本地作用域,赋值的变量除非声明为全局变量,否则均为本地变量。
所有的变量名都可以归纳为本地、全局或内置。
变量名引用在三个作用域中按序查找:本地、函数内、全局、内置。即范围约小,优先级越高。
全局变量¶
全局变量是模块文件内部的顶层的变量名;
如果要在函数内部对全局变量进行复制的话,必须事先使用 global 进行声明;
global关键字后跟一个或多个由逗号隔开的变量名;
全局变量名在函数内部不经声明也可以被引用;
本地变量在函数返回时会消失,而全局变量不会,因此,使用全局变量是保存函数状态信息的最直接办法;
应尽力避免使用全局变量。
参数传递¶
当变量的类型是可变时,用两种方法可以避免可变参数被函数修改:
- 直接传递可变对象的副本:
testFunc(A,B[:]); - 在函数内部创建可变参数的副本:
B=B[:];
参数匹配模型¶
默认情况下,参数通过其位置进行传递,从左至右。所以必须精确地传递和函数参数一样多的函数;
也可以通过关键字参数、默认参数、参数容器等改变这种机制。
关键字参数¶
使用 name=value 的语法通过参数名进行匹配:
1 | def f1(a,b,c): |
默认参数¶
定义函数是指定默认值,那么引用时可不传递相同数量的参数,会直接使用默认值。
注意:带默认值的参数必须处于最右侧。
1 | def f1(a,b=32,c=11): |
可变参数¶
- 定义函数时使用
*开头的参数,在使用函数时可传递任意数量的参数,会自动识别为元组。
1 | def f1(*args): |
- 而使用
**的会被识别为字典。
1 | def f1(**args): |
上面是在定义函数是使用 *,其实也可在传递参数时使用 *。
定义一个函数,以此为基础:
1 | def f1(a,b,c): |
2.把字典作为参数传递:
1 | d1 = {'a':123,'b':456,'c':789} |
3.还可以混合使用:
1 | d1 = {'b':111,'c':222} |
装饰器¶
是一个函数,用途是包装另一个函数,以实现修改或增强被包装对象的功能
@装饰器名称,必须出现在函数的定义之前。
八、模块¶
模块也是一个对象
模块也是一个容器,容器内可以保存很多对象,对象可以通过 import 加载。
1 | import copy |
模块自己定义了一个容器,容器内有许多属性,属性就是在模块内定义的全局变量或其他的名称,全局变量可能是整型、浮点等,只要是顶格定义的都可以理解为全局对象。
获取当前所有可用的模块列表:
1 | help("modules") |
Python 的程序架构:由一个顶层文件,以及一个或多个模块文件组成
导入模块:
import:导入指定的模块整体;并会引入新的名称空间,即模块名;
1 | import copy |
from-import:导入指定的模块的部分属性;把模块的属性直接引入到当前名称空间;
1 | from copy import deepcopy |
模块搜索路径:
- 程序的主目录:
PYTHONPATH变量中定义的各目录;- 标准链接库的目录:
- 任何以
.pth结尾的文本文件中定义的路径;
结合起来在 sys.path 模块里所包含的路径:
1 | import sys |
Python 包¶
将一组模块归并到一个目录,此目录即为包,必须放置在模块的搜索路径下;
1 | import dir1.dir2.mod1 |
九、面向对象编程(OOP)¶
类就是用户自定义的一种可以保存特定数据格式的类型,对这个类型中的属性赋值,能实例化出一个具体的对象。而这个对象能支持什么样的操作,是用户自己设计的。
类之间的关系:
- 依赖
uses-a:一个类的方法操纵另一个类的对象; - 聚合
has-a:类 A 的对象包含类 B 的对象; - 继承
is-a:描述特殊与一般关系。
创建类(class)¶
为了区分函数和类,一般情况下类的首字母要大写,而函数不需要:
1 | class ClassName(bases): # 括号内指定基类,没有可不指定 |
示例:
1 | # 创建类 |
类的主体可以包含:声明语句、类成员定义:
- 任何赋值语句都会创建类属性;
- 如果不存在继承关系,那么基类可以为空;
- 类本身是可执行代码,直到运行后类对象才会存在;
- 实例化的方法:
instance_name = ClassName();- 每个实例化出来的对象,都会继承类的属性,并获得自己的名称空间;
在 Python 中,class 语句类型 def,是可执行代码:
1 | # ↓ 类名 |
通过实例调用的方法,相当于调用所属类的方法来处理当前实例:
- 类似
instance.method(args)会被自动转换为 `class.method(instance,args); - 所以上面例子中的
x.display会被自动转换为FirstClass.display(x),即调用类的方法来处理实例x; - 因此,类中的每个方法必须具有
self参数,为了隐藏当前实例;
统计 Nginx 的客户端数量¶
使用字典,实现统计客户端数量的功能:
1 | # 初始化字典 |