Python3 基础
前言
终于开始正式学习 Python 了。近些年,Python 大火,互联网上下充斥着学了 Python 即可闯遍大江南北的口号与广告。
尽管在如此大环境之下,之前我也一直没想着接触 Python,因为我觉得对于 coder 来说,编程思想才是关键,语言这种东西一通百通,明白了基本语法,以及在尝试编写过程中逐步了解更多的语言特色与使用法则,基本不是难事,Python 尤是。
开始大创之后,对 Python 的接触时长大幅提升,是时候较为系统地了解一下 Python 的一些基础内容了。
目录
1. Python 简介
2. Python 特点
3. Python3 环境搭建
4. Python3 基本语法
1. Python 简介
Python 是一种解释型、面向对象、动态数据类型的高级程序设计语言,于 1989 年发明。
Python2 与 2020 年初停止更新,2.7 为最终版本。
Python3 简称为 Py3k,与 2008 年发布,不向下兼容,目前最新版本为 3.9。
这篇文章主要针对 Python3。
2. Python 特点
> 解释型语言
开发过程没有编译环节,类似于 PHP 与 Perl 等。
> 交互式语言
可以在 Python 提示符 >>> 后直接执行代码。
> 面向对象语言
支持面向对象风格或代码封装在对象的编程技术,同 C++ 与 Java 等。
> 初学者语言
初学者很容易上手,关键字少,结构简单,且支持广泛应用程序开发,从文字处理到浏览器到游戏等。
> 其他
标准库丰富,跨平台;可移植性、可扩展性强。
3. Python3 环境搭建
暂略。
4. Python3 基本语法
4.1. 关键字
Python 标准库提供了一个 keyword 模块,可以输出当前版本所有关键字:
>>> import keyword >>> keyword.kwlist ['False', 'None', 'True', 'and', 'as', 'assert', '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']
4.2. 标识符
标识符不能为关键字,第一个字符必须为大小写字母或下划线 _,对大小写敏感。可以用非 ASCII 字符(比如中文)作为标识符。
4.3. 注释
单行注释以 # 开头,多行注释以 ''' 或 """ 开始与结束。举例:
# 这是单行注释 ''' 这是多行注释 ''' """ 这是多行注释 """
尽管单引号与双引号版本效果相同,但在 PEP8 规范中建议双引号用于文档注释,而单引号用于类与对象内注释,一般也尽可能去遵循它;否则可能出现诸如 “Triple double-quoted strings should be used for docstrings. ” 的提示。
4.4. 行与缩进
4.4.1. 缩进
缩进是 Python 最具特色的内容之一。不同于 C, Java 等使用 {} 表示代码块,Python 直接用缩进表示,那么也就是说,缩进也是 Python 语法规范的一部分,如果缩进不符合规范,则可能出现语法错误,这也一定程度上对代码格式进行了规范。
如下代码被认为是不规范的:
if True: print(1) else: print(0)
导致出现 “PEP 8: E111 indentation is not a multiple of four” 的提示。
如下代码被认为是语法错误:
a = 0
b = 0
4.4.2. 多行语句
除了缩进有严格要求,Python 同样不允许同一条语句出现换行。但有时语句确实非常长,如果不换行,可读性很差,所以 Python 规定可以使用反斜杠 \ 表示长语句换行,例如:
total = alice + bob + \
carol + dave + eve
注意,如果长语句包括于各种括号中(比如 [], (), {}),则不需要反斜杠。
4.4.3. 多条语句
多个语句可以写在同一行,中间用分号相隔。
4.5. 变量与基本数据类型
Python 中的变量不需要声明,在赋初值时就相当于同时声明了。同时,变量本身无需给出数据类型,我们所说的类型是指变量所指向的内存中对象的类型。
赋值使用等号 =,允许多个变量赋同一个值,允许一条语句为多个变量赋值,例如:
a = b = c = 1
a, b, c = 1, 2, 3
Python 有六大基本数据类型:Number(数字),String(字符串),List(列表),Tuple(元组),Set(集合),Dictionary(字典),下面依次介绍。
4.5.1. 数
数(Number),有四种类型:
int 整数,bool 布尔数,float 浮点数,complex 复数。例如:
a, b, c, d = 1, 2.0, True, 3 + 4j
它们分别对应如上四种数的类型。复数的实部与虚部均为浮点数,除了 a + bj 形式,还可以用 complex(a, b)。
Python 内置了 type 函数,用于查询变量所指的对象类型;以及 isinstance 函数,用于判定类型。例如:
print(type(a)) print(isinstance(a, float))
分别输出 <class 'int'> 和 False。
可以使用 del 语句来删除单个或多个对象。例如:
del a del a, b
数值运算大同小异。其中,/ 表示非整除除法,// 表示整除,** 表示乘方。例如:
>>> 2 / 4
0.5
>>> 2 // 4
0
>>> 2 ** 5
32
后面会有更多关于运算符的介绍。
整数还可以使用十六进制、八进制来表示。例如:
num1 = 0xABC
num2 = 0o566
4.5.2. 字符串
字符串(string),由一个或多个字符组成的一种数据类型。在 Python 中没有单独的字符类型,单字符即长度为 1 的字符串;同注释一样,单引号和双引号作用是相同的,同时,还可以使用三引号指定一个多行字符串。比如:
a = 'word' b = "This is a sentence." c = ''' paragraph 1 paragraph 2 '''
字符串中可以使用加号 +,表示直接相连;可以使用乘号 *,表示重复。比如:
d = 'outer' + 'wilds' e = 'be' * 2
字符串中可以使用反斜杠 \,表示转义字符,如下为常用转义字符:
① \ + \ ' '' 输出后者字符
② \a 响铃
③ \b 退格
④ \n 换行
⑤ \r 回车
⑥ \t 横向制表符
⑦ \v 纵向制表符
如果在字符串前加上 r 或 R(raw,未加工的),可使反斜杠不表示转义。
f = 'icpc\n2020' g = r'icpc\n2020'
前者的 “icpc” 与 “2020” 之间为换行符 \n,后者则为 “icpc\n2020”。
字符串支持双向索引。除下标为 0 开始表示从左至右索引,还可以为负数,从 -1 开始表示从右至左索引。比如 a[-2] 表示字符串 a 的倒数第二个字符。
字符串输出时,可以只截取其中一部分,截取语法格式如下:
字符串变量名[下标]
表示截取指定下标的一个字符。
字符串变量名[头下标 : 尾下标 : 步长]
表示截取以一定步长从头下标至尾下标前一位(左闭右开)的字符串;步长为 n 时表示每间隔 n 个字符输出一个字符,当 n 为负数时,表示逆向截取。
其中,三个参数均可缺省。
> 步长可缺省,默认值为 1,缺省时第二个冒号同时省略;
> 头下标可缺省,默认值为 0;
> 尾下标可缺省,默认值为字符串长度;
第一个冒号无论如何均不可省略,否则可能与只输出一个字符的情况产生二义性。
例子如下:
a = 'word' print(a[0]) # print w print(a[0:2]) # print wo print(a[-3:-1]) # print or print(a[1:]) # print ord print(a[:3]) # print wor print(a[:]) # print word print(a[1::2]) # print od
字符串不允许向某一个索引位置赋值,比如 a[1] = 'p' 之类的,属于不可变数据。
上面的截取方式不局限于字符串类型。
> 格式化
Python 支持格式化字符串的输出,类似于 C 中的 sprintf,格式为:
print(带格式化符号的字符串 % 格式化元组)
例如:
>>> print("Hello, %s(%d)!" % ('jinkun113', 2021)) Hello, jinkun113(2021)!
常用的格式化符号如下:
① %c 格式化字符及其 ASCII 码
② %s 格式化字符串
③ %d 格式化整数
④ %f 格式化浮点数
> str.format
Python 还提供了 str.format 函数,以增强格式化的功能,格式为:
带 {} 的字符串.format(格式化参数)
有如下几种不同的使用方式:
>>>"{} {}".format("Outer", "Wilds") # 不设置指定位置,按默认顺序 'Outer Wilds' >>> "{0} {1}".format("Outer", "Wilds") # 设置指定位置 'Outer Wilds' >>> "{1} {0} {1}".format("Outer", "Wilds") # 设置指定位置 'Wilds Outer Wilds' >>> "名称:{name}, 地址 {url}".format(name="jinkun113", url="www.runoob.com") '名称:jinkun113, 地址 www.cnblogs.com/jinkun113' dict = {"name": "jinkun113", "url": "www.cnblogs.com/jinkun113"} # 使用字典来设置参数 list = ['jinkun113', 'www.cnblogs.com/jinkun113'] # 使用列表来设置参数 >>> "名称:{name}, 地址 {url}".format(**dict) '名称:jinkun113, 地址 wwww.cnblogs.com/jinkun113' >>> "名称:{0[0]}, 地址 {0[1]}".format(list) '名称:jinkun113, 地址 www.cnblogs.com/jinkun113'
还有一系列格式化数字的方法:
① {:.*f} 保留小数点后 * 位
② {:x>*d} 向数字左侧填充 x,宽度为 *(改为 < 为右侧,缺省 x 时为直接左右对齐)
③ {:,} 改为逗号分隔式数字
④ {:.*%} 改为保留 * 位的百分比格式(改为 e 为科学计数法格式)
> f-string
Python 3.6 后的版本添加了 f-string,即字面量格式化字符串。
暂略。
4.5.3. 列表
列表(List),是 Python 中使用最频繁的数据类型,可以完成大多数集合类的数据结构的实现。列表中各个元素的类型可以不痛,支持数字、字符串甚至列表(即嵌套)。定义列表的一般格式如下:
列表名 = [元素 A, 元素 B, ...]
和字符串一样,列表可以被索引和截取,可以连接与重复,且语法格式一致,不再介绍。
举个例子:
List1 = [1, 'hello', 2.33, "It's me", 0] List2 = [3, List1] List3 = List1 * 2 + List2
>>> print(List1[1:5:2]) ... print(List3) ['hello', "It's me"] [1, 'hello', 2.33, "It's me", 0, 1, 'hello', 2.33, "It's me", 0, 3, [1, 'hello', 2.33, "It's me", 0]]
不同的是,列表的元素可以被改变,不论是单个元素还是截取区间的元素。
List 还内置了许多方法。暂略。
4.5.3. 元组
元组(Tuple)与列表类似,但是写在小括号中,且不能被修改。
尽管元组不可被改变,但它可以包含可变的对象,比如列表。
其诸多特性也相同于字符串与列表,不再赘述。
仅包含 1 个元素的元组比较特殊,需要在元素后添加一个逗号。例如:
Tuple1 = (2, )
没有逗号,则会被看作单个元素。
4.5.4. 集合
集合(Set)写在花括号中,和数学概念的集合一样,它是无序的,且重复的元素会被自动去掉。
定义集合有两种方式,如下:
Set1 = {1, '2', "88888"} Set2 = set('shakalaka') Set3 = set('balabala')
集合支持差集、并集、交集、非交集运算,如下:
>>> print(Set2 - Set3) {'h', 's', 'k'} >>> print(Set2 | Set3) {'a', 'b', 'k', 'h', 's', 'l'} >>> print(Set2 & Set3) {'a', 'l'} >>> print(Set2 ^ Set3) {'b', 'k', 'h', 's'}
4.5.5. 字典
字典(Dictionary),也是无序的,并且其元素的值(Value)是通过键(Key)来获取,而非偏移量,类似于 C++ 中的 map(映射)。例如:
Dict1 = {} Dict1['one'] = "1 - ONE" Dict1[2] = "2 - TWO" Dict2 = {'Name': 'J.K.', 'ID': 'jinkun113', 'Location': 'Beijing'} >>> print(Dict1[2]) 2 - TWO >>> print(Dict1.keys()) dict_keys(['one', 2]) >>> print(Dict1) {'one': '1 - ONE', 2: '2 - TWO'} >>> print(Dict2['ID']) jinkun113 >>> print(Dict2.values()) dict_values(['J.K.', 'jinkun113', 'Beijing'])
字典和集合一样是使用花括号,不同的是字典需要同时定义键与值;同时需要注意的是,如果是直接使用 {},则表示建立的是空字典,而非空集合,空集合只能使用 set() 来建立。
字典还可以使用构造函数 dict() 来建立,例如:
>>> dict([('ONE', 1), ('TWO', 2), ('THREE', 3)]) {'ONE': 1, 'TWO': 2, 'THREE': 3} >>> {x: x ** 2 for x in (2, 4, 6)} {2: 4, 4: 16, 6: 36} >>> dict(ONE=1, TWO=2, THREE=3) {'ONE': 1, 'TWO': 2, 'THREE': 3}
4.5.6. 数据类型转换
数据类型转换很简单,直接将类型名作为函数名即可,例如:
a = 123 >>> print(float(a)) 123.0 >>> print(hex(a)) 0x7b
a = [1, 2, '3', 2] >>> print(tuple(a)) (1, 2, '3', 2) >>> print(set(a)) {1, 2, '3'}
4.6. 运算符及其优先级
运算符分为如下七类:
算数、关系、赋值、逻辑、位、成员、身份运算符。
其中大部分都无需在介绍,仅介绍在 Python 中比较特别的。
4.6.1 运算符
> 逻辑运算符 and / or / not
a = 1 b = 2 >>> print(a and b) 2 >>> print(a or b) 1 >>> print(not a) False
> 成员运算符 in
a = 1 b = 2 c = 3 List5 = {1, 3, 5} >>> print(a in List5) True >>> print(b in List5) False >>> print(c not in List5) False
> 身份运算符 is
is 与 == 类似,后者为判断变量引用对象的值是否相等,而前者判断变量引用的是否为同一个对象。Python 提供 id 函数,用于获取对象的内存地址,也就是说,x is y 等价于 id(x) == id(y)。例如:
a = [1, 2, 3] b = a c = a[:] >>> print(b is a) True >>> print(b == a) True >>> print(c is a) False >>> print(c == a) True
Python 对较小的数有优化机制,-5 到 256 区间内的所有数会被预先创建,并存在一个固定的内存空间上;创建变量时如果初值为这个区间的数,则其指向的内存地址也会是一样的。并且,对于使用分号间隔的多条语句,如果有多个变量的初值相同,其内存地址也会指向相同位置。例如:
a = 10 b = 10 >>> print(a is b) True
a = 1000 b = 1000 >>> print(a is b) False
a = 1000; b = 1000 >>> print(a is b) True
4.6.2. 优先级
从高到低依次为:
① **
② ~ + -(一元加减法)
③ * / % //
④ + -
⑤ << >>
⑥ &
⑦ ^ |
⑧ <= < > >=
⑨ == !=
⑩ = %= /= //= -= += *= **=
⑪ is is not
⑫ in not in
⑬ not and or
4.7. print 输出
Python 使用 print 函数来输出,上面已经演示了。默认情况下输出是换行的,如果不换行,则加上第二个参数 “end='*'”,如下:
print(1, end='') print(2, end=',')
* 可缺省,即只起到不换行的作用;非缺省时,则是在输出内容后自动添加指定字符 *。
后面将有更多关于输入和输出的介绍。
4.8. 条件与循环语句
4.8.1. if 语句
Python 中,条件语句仅有 if 一种,没有 switch - case 语句。
else if 在 Python 中被精简为 elif,所以关键字为 if - elif - else。
用冒号 : 来表示语句块的开始,用缩进来划分语句块,下同。
当 if 语句块中仅有一条语句时,可以将该语句直接接在 : 之后,下同。
4.8.2. while 语句
Python 中没有 do - while 循环。
while 后面可以接 else,表示 while 中的条件语句为 False 时执行的内容。
4.8.3. for 语句
for 可以遍历任何序列中的项目,如果是数字序列,则使用内置的 range() 函数,其三个参数和字符串截取相同,即首尾与步长,此处略;而如果只有一个参数 x,则表示从 0 到 x - 1 的序列。
举个例子:
for i in range(1, 10, 2): print(i)
循环语句同样可以使用 break 和 continue。
4.8.4. pass 语句
Python 提供 pass 语句,表示空,不做任何事情,一般用作占位,可以保持程序结构的完整性。
4.9. 迭代器与生成器
4.9.1. 迭代器
Python 提供迭代器(Iterator),以遍历字符串、列表或元组对象的元素。它从第一个元素开始访问,直到最后,只能往前遍历。其两大基本方法:iter() 和 next(),分别表示创建迭代器对象与返回迭代器下一个元素。举个例子:
list=[1,2,3,4] it = iter(list) >>> print(next(it)) 1 >>> print(next(it)) 2
迭代器对象可以使用 for 语句进行遍历。
迭代器可以通过类进行自定义,在下面的面向对象部分中会提到。
4.9.2. 生成器
在 Python 中,使用了 yield 的函数被称为生成器(Generator),其返回的不是值,而是迭代器。在调用过程中,每次遇到 yield 语句时,函数会暂停并保存当前所有运行信息,返回 yield 的值,并在下一次执行 next() 时从当前位置继续执行。
下面是使用生成器实现的 Fibonacci 数列的代码:
def fibonacci(n): a, b, counter = 0, 1, 0 while True: if (counter > n): return yield a a, b = b, a + b counter += 1 f = fibonacci(10) while True: try: print (next(f), end=" ") except StopIteration: sys.exit()
4.10. 函数
函数是组织好的、可重复使用的代码段。Python 中有许多内建函数,比如 print(),同样可以自定义函数,以关键词 def 开头。
和变量一样,Python 的函数没有规定返回类型。
关于参数,Python 允许设置默认参数,以关键字来传入参数值,允许参数个数不定长(在固定函数后加上一个带星号 * 的元组以存放所有未命名的参数,或者带两个星号 ** 表示以字典形式导入)。
Python 提供 lambda 函数,来创建匿名函数,其只是一个表达式,比 def 形式简单。比如:
c = lambda a, b: a + b
4.11. 数据结构
由于 Python 内置了诸如列表、元组、集合、字典等数据类型,所以要使用数据结构时尤为轻松。
对于列表,其内置有如下方法:
> list.append(x) 将 x 添加到列表的末尾
> list.extend(L) 将列表 L 添加到该列表的末尾
> list.remove(x) 删除列表中值为 x 的第一个元素;如果不存在则会返回错误
> list.pop(x) 删除列表中位置为 x 的元素,并返回该值;可缺省,表示最后一个元素
> list.clear() 删除列表中的所有项,等价于 del a[:]
> list.index(x) 返回列表中值为 x 的第一个元素的索引;如果不存在则会返回错误
> list.count(x) 返回值为 x 的元素的个数
> list.sort(cmp=None, key=None, reverse=False) 对列表元素进行排序,默认为升序排序,cmp 表示排序参数,key 表示用来比较的元素名,reverse 为 True 时为降序。
> list.reverse() 将列表中的元素倒序
> list.copy() 返回列表的浅复制(浅复制表示两个对象指向同一内存地址,对应概念为深复制)
根据上述方法,将列表当做栈来使用就非常方便了,借助 append 和 pop 即可实现;队列其实也好实现,但效率并不高。
4.12. import 与模块
Python 使用 import 或者 from...import 语句来导入模块。
将整个模块导入,使用 import,例如:
import sys
将某个模块的一个、多个或全部函数导入,使用 from...import,例如:
from sys import argv from sys import argv, path from sys import *
将整个模块导入和将模块的全部函数导入并非等价。前者相当于导入该文件夹,后者相当于导入文件夹内所有文件;所以,前者在引用其中函数时需要加上模块名,后者则可以直接使用。
4.13. 输入输出与文件 File
4.13.1. 读取键盘输入
Python 内置了 input() 函数,以从标准输入读入一行文本,默认标准输入是键盘。可以填入需要展示在标准输入上的内容,例如:
>>> str = input("name: ") name:
输出函数 print() 上面已经介绍了。
4.13.2. 读写文件
Python 内置了 open() 函数,以对一个 file 对象即文件,进行访问。一般格式如下:
open(file, mode='r')
而完整格式其实如下:
open(file, mode='r', buffering=-1, encoding=None, errors=None, newline=None, closefd=True, opener=None)
参数说明:
> file 唯一必需,表示文件路径(相对或绝对均可)
> mode 文件打开模式
下面是模式与功能的对应关系。
rb, rb+, wb, wb+, ab, ab+ 模式在原基础上加上 b,表示以二进制格式打开。
> buffering 设置缓冲
> encoding 编码方式,一般为 UTF-8
> errors 报错级别
> newline 区分换行符
> closefd 传入的 file 参数类型
> opener 自定义开启器
对于 file 对象,有如下方法:
> file.read(size) 读取文件中大小为 size 的数据,返回一个多行字符串;size 如果缺省或为负数,则读取所有数据
> file.readline() 读取文件中单独的一行数据,以换行符 \n 结束,返回一个字符串
> file.readlines() 读取文件中每一行的数据,返回一个列表
> file.write(str) 将 str 写入到文件中,并返回字符数
> file.tell() 返回文件对细想当前所处位置,即从文件开头开始算起的字节数
> file.seek(a, b) 改变文件当前位置,当 b = 0 时,从文件首字母往后移动 a 个字符;b = 1 时,从当前位置往后移动 a 个字符;b = 2 时,从结尾位置往前移动 -a 个字符。
> file.close() 关闭文件,并释放系统资源;
举个例子:
f = open("1.txt", "w") f.write("Hello, world!") f.close()
4.14. 系统 OS
Python 提供了 os 模块,里面有丰富的方法来处理文件与文件目录。常用方法如下:
> os.access(path, mode) 检验权限模式
> os.chdir(path) 改变当前工作目录
> os.chmod(path, mode) 更改权限
> os.chchown(path, uid, gid) 更改文件所有者
> os.close(fd) 关闭文件描述符 fd
> os.listdir(path) 返回 path 指定的文件夹包含的文件和文件夹的名字的列表
> os.makedirs(path, mode) 递归文件夹创建函数,mkdir 方法类似,
4.16. 错误与异常
4.17. 面向对象
4.18. 标准库一览
4. 命令行参数