Python基础知识目录
一、初始Python
1. 解释和编译
计算机只能理解机器语言,所以高级语言必须翻译成机器语言才能被计算机所执行,将其他语言翻译成机器语言的工具叫做编译器。
编译器翻译的方式有两种:一种是编译,一种是解释(又称作解释器)。两种方式的区别在于翻译时间点的不同。
- 编译型语言:在程序执行之前,先把整个高级语言源程序通过编译器翻译成机器语言后就不再进行翻译,是一个单独的编译过程,运行时不需要重新编译直接使用编译结果,程序执行效率高,但跨平台性较差,如C语言。
- 解释型语言:在运行的时候将程序逐条翻译成机器语言并逐条执行,运行时必须先解释再执行,具有跨平台性,如JavaScript。
Python属于解释型语言,但带有一些编译的特性。执行过程中先把源码.py文件编译成字节码.pyc或者.pyo文件,再由Python的虚拟机执行。效率高于传统的解释型语言。
2. Python语言特点
- 免费和开源:Python是FLOSS(自由/开放源码软件)之一,允许自由的发布软件的备份、阅读和修改其源代码、将其一部分自由地用于新的自由软件中。
- 简单高效:语法简洁,结构清晰,简单易学。
- 丰富的生态系统:拥有丰富的标准库(如GUI、爬虫、机器学习等),庞大的第三方库(如NumPy、Matploylib、Pandas等),对底层OS有良好的兼容性。
- 高可扩展性:可快速集成其他语言编写的程序,如通过C、C++语言为Python编写扩充模块。
- 可移植性:能运行在不同的平台上。
- 可嵌入性:可以嵌入到C、C++中,为其提供脚本功能。
3. Python基础语法
- 动态性语言,变量使用前不需要声明;
- 标识符区分大小写,第一个字符必须是字母或下划线,其他字符由字母、下划线、数字组成;
- print()函数输出时自动换行;
- 语句块通过代码的缩进来表示;
- 乘法可以用在字符串中,如 "_ "*5
- 数据类型:(1)数字型:整形、浮点型、布尔型、复数型;(2)非数字型:字符串、列表、元组、字典、集合;
- 变量的输入: input()函数,输入的数据类型都是字符串类型;
- 转义字符
转义字符 | 描述 | 转义字符 | 描述 |
---|---|---|---|
\r | 回车 | \\(行尾) | 续行符 |
\n | 换行 | \\\ | 反斜杠 |
\t | 横向制表符 | \\' | 单引号 |
\v | 纵向制表符 | \\" | 双引号 |
\f | 换页 | \\000 | 空 |
\a | 响铃 | \\oyyy | 八进制 |
\b | 退格s | \\xyy | 十进制 |
- 失效转义字符:r’字符串’ 或 R’字符串’
print(r"C:\DevelopmentEnvironment\python36")
#等同于
print("C:\\DevelopmentEnvironment\\python36")
#都输出C:\DevelopmentEnvironment\python36
- end参数:end="",输出不换行
#\n换行,结果打印两行
print("逆风如解意,\n容易莫摧残。")
#end参数,结果打印在同一行
print("逆风如解意,",end="")
print("容易莫摧残。")
二、基础知识
1. 数据类型
- 数字、字符串、列表、元组、字典、集合
#整数int、浮点数float、布尔值Boolean、复数Complex
int_num=1234567890
#type()打印数据类型
print(int_num,type(int_num)) #1234567890 <class 'int'>
float_sun=1.392E9#太阳的直径1392000km
print(float_sun,type(float_sun)) #1392000000.0 <class 'float'>
bool_=True
print(bool_,type(bool_)) #True <class 'bool'>
complex_=1+2j
print(complex_,type(complex_)) #(1+2j) <class 'complex'>
2. 常量、变量
- 常量:数字、字符串、布尔值、空值等,如2、-3.5、True、False、“Python”、None
- 变量:不需要声明、数据类型由所赋值来决定、不同类型数据运算时,自动进行类型转换,优先级如下:
bool < int < float < complex
a=10
b=3.5
print(a+b,type(a+b)) #13.5 <class 'float'>
函数 | 功能 |
---|---|
int(x,base) | 转化为整型,base表示转换后进制 |
float() | 转化为浮点型 |
bool() | 转化为布尔型 |
str() | 转化为字符串 |
chr() | 将整数转换为对应的ASCII字符 |
ord() | 将一个字符转化为对应的ASCII码 |
complex() | 转化为复数型 |
a="11"
b=int(a)+1
print("a=",a,type(a)) #a= 11 <class 'str'>
print("b=",b,type(b)) #b= 12 <class 'int'>
print(int(-3.5) #-3,取整结果趋于0方向
print(chr(65)) #A
print(ord('A')) #65
print(complex(1)) #(1+0j)
3. 运算符
- 算数运算符
算术运算符 | 描述 |
---|---|
+ | 加 |
- | 减 |
* | 乘 |
/ | 除 |
% | 求模(取余) |
** | 幂 |
// | 整除 |
print(7.0//2,-7.0//2) #3.0 -4.0
print(-7%2,7%-2) #1 -1
- 赋值运算符
赋值运算符 | 描述 | 赋值运算符 | 描述 |
---|---|---|---|
= | 直接赋值 | /= | 除法赋值 |
+= | 加法赋值 | %= | 取模赋值 |
-= | 减法赋值 | **= | 幂赋值 |
*= | 乘法赋值 | //= | 整除赋值 |
#连续赋值
a=b=c=1
print(a,b,c) #1 1 1
#多元赋值
x,y,z=1,2,'Hello'
print(x,y,z) #1 2 Hello
- 逻辑运算符:True(非0、非空集合)、False(0、空集)
逻辑运算符 | 描述 |
---|---|
and | 与 |
or | 或 |
not | 非 |
- 比较运算符
比较运算符 | 描述 |
---|---|
== | 等于 |
!= 或<> | 不等于 |
< | 小于 |
> | 大于 |
<= | 小于等于 |
>= | 大于等于 |
- 位运算符
位运算符 | 描述 | 事例 |
---|---|---|
& | 与 | 1&0=0 |
| | 或 | 1|0=1 |
^ | 异或 | 1^0=1 |
~ | 非 | ~1=0 |
<< | 位左移 | 1<<2=4 |
>> | 位右移 | 4>>1=2 |
- 字符串运算符
字符串运算符 | 描述 |
---|---|
+ | 字符串连接 |
* | 重复输出字符串 |
py="python"
v3="3.0"
print(py+" "+v3) #python 3.0
print("说三遍"*3) #说三遍!说三遍!说三遍!
- 成员运算符
成员运算符 | 描述 |
---|---|
in | 字符串中包含给定的字符,返回True,否则返回False |
not in | 字符串中不包含给定字符,返回True,否则返回False |
str="Hello!"
'H' in str #True
#'h' in str #False
4. 条件语句
- if语句
- if-else语句
- if-elif-else语句
x=int(input("x:"))#4
y=int(input("y:"))#3
if x<y:
print("x is less than y.")
elif x>y:
print("x is greater than y.")
else:
print("x is equal to y.")
print("continue...")
#x is greater than y.
#continue...
- while语句
#前100累加和
i=1
sum=0
while i<=100:
sum+=i
i+=1
print(sum) #5050
- for循环
- continue语句:终止本次循环,开始下一次循环
- break语句:跳出循环体,结束循环
#前100奇数和
sum1=0
#range(起始值,末尾值,步长),range范围中不包含末尾值
for i in range(1,101,1):
if i%2==0:
continue
sum1+=i
print(sum1) #2500
sum2=0
for i in range(1,101,2):
if sum2<=2000:
sum2+=i
else:
break
print(sum2) #2025
三、数据结构
1. 列表 list[ ]
list是一种有序的集合,可以随时添加和删除其中的元素,list可为空,例如:L= [ ],Python是动态语言,所以list中包含的元素并不要求都必须是同一种数据类型,例如:L=[‘Michael’,100]
L = ['Adam', 'Lisa', 'Bart', 'Paul']
print(len(L)) #4
#正序访问list,使用索引时,注意不要越界
print(L[0]) #Adam
#倒叙访问list
print(L[-2]) #Bart
#添加元素,append()方法将元素添加至list末尾
L.append('Patrick')
print(L) #['Adam', 'Lisa', 'Bart', 'Paul', 'Patrick']
#插入元素 insert()
L.insert(0,'Bob')
print(L) #['Bob', 'Adam', 'Lisa', 'Bart', 'Paul', 'Patrick']
#删除元素 pop()
L.pop(1)
print(L) #['Bob', 'Lisa', 'Bart', 'Paul', 'Patrick']
#替换元素
L[1]='Ben'
print(L) #['Bob', 'Ben', 'Bart', 'Paul', 'Patrick']
#合并列表extend()或'+'
L2=['David']
print(L2+L) #['David', 'Bob', 'Ben', 'Bart', 'Paul', 'Patrick']
L.extend(L2)
print(L) #['Bob', 'Ben', 'Bart', 'Paul', 'Patrick', 'David']
#列表排序
L3=[2,5,3,6,4,8,9,6]
L3.sort()#对列表中元素排序
print(L3) #[2, 3, 4, 5, 6, 6, 8, 9]
L3.reverse()#对列表中元素倒叙
print(L3) #[9, 8, 6, 6, 5, 4, 3, 2]
list[ ]切片:
- 索引第2-4个元素,L[1:4]表示从索引1开始,到索引4为止但不包含索引4
- 第一个索引是0可省略,L[:3]
- 只用一个“:”,表示从头到尾,L[:]实际上复制出了一个新list
- 指定参数,L[::n],表示每n个取一个,例如L[1,2,3,4,5,6],L[::2]>>>[1,3,5]
- 上述方法同理适用于倒叙切片
L=list(range(1,101))
#前10个数
print(L[:10]) #[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
#3的倍数
print(L[2::3]) #[3, 6, 9, 12, 15, 18, 21, 24, 27, 30, 33, 36, 39, 42, 45, 48, 51, 54, 57, 60, 63, 66, 69, 72, 75, 78, 81, 84, 87, 90, 93, 96, 99]
#不大于50的5的倍数
print(L[4:50:5]) #[5, 10, 15, 20, 25, 30, 35, 40, 45, 50]
#最后10个数
print(L[-10:]) #[91, 92, 93, 94, 95, 96, 97, 98, 99, 100]
#最后10个5的倍数
print(L[-46::5]) #[55, 60, 65, 70, 75, 80, 85, 90, 95, 100]
2. 元组 tuple( )
tuple是一种有序的列表,tuple一旦创建完毕,就不能修改了,可空
t1=(1)
print(t1,type(t1)) #1 <class 'int'>
t2=(1,)#单元素tuple要多加一个逗号“,”
print(t2,type(t2)) #(1,) <class 'tuple'>
#可变的tuple
t=('a','b',['A','B'])#tuple中list表不可变,但list中的元素可以改变
3. 字典 dict{ }
d = {key1 : value , key2 : value , …},有如下特点:
- 查找速度快,所有元素查找速度一样,但浪费内存
- dict按key查找,一个dict中key值不能重复
- 所有元素有序(3.6版本之前是无序的)
d={'Adam':95,'Lisa':85,'Paul':75,'Bart':59}
print(len(d)) #4
#访问dict,使用key索引value
print(d['Adam']) #95
#print(d['Ben']) 不存在的key输出会报错
#in操作符判断key值是否存在
if 'Lisa' in d:
print(d['Lisa']) #85
if 'Bob' in d:
print(d['Bob']) #不打印任何值
#get方法
print(d.get('Bart')) #59
print(d.get('Patrick')) #None
#添加元素
d['Patrick']=99
#修改元素
d['Lisa']=65
#删除元素
d.pop('Bart')
print(d) #{'Adam': 95, 'Lisa': 65, 'Paul': 75, 'Patrick': 99}
#keys()返回字典中所有关键字
print(d.keys()) #dict_keys(['Adam', 'Lisa', 'Paul', 'Patrick'])
#values()返回字典中所有值
print(d.values()) #dict_values([95, 65, 75, 99])
#items()返回字典中所有键值对
print(d.items()) #dict_items([('Adam', 95), ('Lisa', 65), ('Paul', 75), ('Patrick', 99)])
#格式化参数
for key,val in d.items():
#引号里的%s是格式化参数,key是变量,%s表示num是float类型
print("d[%s] =" %(key),val,end=" ") #d[Adam] = 95 d[Lisa] = 65 d[Paul] = 75 d[Patrick] = 99
#清空字典clear()
d.clear()
print(d) #{}
4. 集合 set( )
set由一组无序排列的元素组成,set的内部结构和dict很像,唯一区别是不存储value。
- 可变集合 set( )
- 不可变集合 frozenset( )
s = set(['A', 'B', 'C', 'C'])#set会自动去掉重复的元素
print(s)
'D' in s #False
四、函数
1. Python内置函数
函数 | 说明 |
---|---|
abs(x) | 返回x绝对值 |
pow(x,y) | 返回x的y次幂 |
round(x,[n]) | 返回浮点数x的四舍五入值,指定保留n位笑鼠,默认为0 |
divmod(a,b) | 返回a÷b的商和余数的元组 |
len() | 返回长度 |
max() | 返回最大值 |
sum() | 返回总和 |
str() | 转换成字符串 |
float() | 转换成浮点型 |
int() | 转换成整型 |
list() | 转换为列表 |
help() | 显示帮助信息 |
dir() | 显示属性 |
type() | 显示类型 |
range() | 返回一个整型列表 |
open() | 打开文件 |
2. 函数变量
- 局部变量:创建函数中定义的变量,仅再定义它的函数内有效;
- 全局变量:函数体外定义的变量,在之后的代码块中都有效。
a=100#全局变量
b=23#全局变量
def setNumber():
a=9#局部变量
print(a,b) #9 23
setNumber()#调用函数,打印局部变量
print(a,b) #100 23
3. 参数
- 位置参数:实际调用参数(实参) 的对应关系与形式参数(形参)的对应关系是按位置来依次对应的。
def sum1(a,b):
sum=a+b
print(sum1)
sum1(1,2) #3
- 默认参数:放在必选参数之后,必须指向不变对象
#计算x的n次幂
def power(x,n=2):
s=1
while n>0:
n-=1
s*=x
return s
print(power(2)) #4
power(5,3) #125
- 可变参数:传入的参数个数可变,参数前面加上 * 就是可变参数,调用list和tuple中的元素时用可变参数
#计算平方和
def calc(*numbers):
sum=0
for n in numbers:
sum=sum+n*n
return sum
print(calc(1,2,3,4,5,)) #55
calc(1,2,3) #14
- 关键字参数:实参和形参按名称进行匹配,**表示关键字参数,允许传入0个或任意个含参数名的参数,这些关键字参数在函数内部自动组装成一个dict
- 命名关键字参数:在关键字参数的基础上限制传入的的关键字的变量名
def person(name,age,**kw):
print("name:",name,"age:",age,"other:",kw)
person('Lisa',26, city="Beijing") #name: Lisa age: 26 other: {'city': 'Beijing'}
#也可以类似可变参数,先组装一个dict,然后,把该dict转换为关键字参数传进去
kw={'city':'Beijing', 'job':'Engineer'}
person('Jack', 24, city=kw['city'], job=kw['job']) #name: Jack age: 24 other: {'city': 'Beijing', 'job': 'Engineer'}
- 参数组合:参数定义的顺序位置参数、默认参数、可变参数、关键字参数、命名关键字参数
def f1(a,b,c=0,*args,**kw):
print("a =",a,"b =",b,"c =",c,"args =",args,"kw =",kw)
def f2(a,b,c=0,*,d,**kw):
print("a =",a,"b =",b,"c =",c,"d =",d,"kw =",kw)
f1(1,2) #a = 1 b = 2 c = 0 args = () kw = {}
f1(1,2,c=3) #a = 1 b = 2 c = 3 args = () kw = {}
f1(1,2,3,'a','b') #a = 1 b = 2 c = 3 args = ('a', 'b') kw = {}
f1(1,2,3,'a','b',x=99) #a = 1 b = 2 c = 3 args = ('a', 'b') kw = {'x': 99}
f2(1,2,d=99, x=None) #a = 1 b = 2 c = 0 d = 99 kw = {'x': None}
4. 模块、包、库
- 模块:一个Python文件(.py)拥有多个功能相近得函数或类,便于代码复用,提高可维护性,可以避免函数名和变量名冲突。
- 包:避免模块名冲突,按目录来组织模块,一个包对应一个文件夹,功能相近得模块放在一个文件夹中。包目录下第一个文件便是 __init__.py
- 库:具有相关功能模块的集合。Python具有强大的标准库、第三方库以及自定义模块。
- 标准库:下载安装的Python里那些自带的模块。
- 第三方库:其他的第三方机构,发布的具有特定功能的模块。
- 自定义模块:用户自己可以自行编写模块,然后供自己使用。
五、面向对象
1. 初识面向对象
了解面向对象之前,先了解一下面向过程,面向过程的程序设计的核心是过程(流水线式思维),过程即解决问题的步骤,面向过程的设计就好比精心设计好一条流水线,提前考虑好什么时候处理什么东西,极大的降低了写程序的复杂度,只需要顺着要执行的步骤编写就行,但一套流程只能用来解决一个问题。应用于一旦完成基本很少改变的场景,比如Linux內核,git,Apache HTTP Server等。
面向对象的程序设计的核心是对象,比如事物的某一具体属性即可理解为对象。面向对象解决了程序的扩展性问题,对某一个对象单独修改,会立刻反映到整个体系中,但可控性差。
下面来理解几个概念(结合后面的内容来理解):
- 类:是具有相同属性和方法的对象集合,子类(派生类)继承父类(基类)全部的属性和方法,并且拥有自己特有的属性和方法。
- 对象(实例):对象是类的具体实例,把数据和程序进行封装,需要用类来创造一个对象。对象只有一种作用:属性引用。
- 属性:类和对象中的变量。
- 类属性:定义在类的内部,方法的外部,类中所有对象共同拥有的属性。
- 实例属性:又叫成员变量,在每个对象中都有自己的副本。
- 方法(函数):类中定义的函数,描述对象能执行的操作。
- 实例方法:只能通过对象调用。
- 实例化:类→对象的过程。
tips:在Python中,函数名一般是以小写字母开头 ,类名是以大写字母开头。
类的相关知识
#声明类
class 类名:
类属性=初值
def 方法(self参数列表) #方法是类中定义的函数,描述对象能够执行的操作
#创建对象
对象名=类名(参数)
下面看一个实例:
class Person():#声明Person类
money=10000#Person类中创建money属性这一具体实例
def say_hello(self):#创建say_hello方法
print("Hello!")
zhangsan=Person()#创建zhangsan这个Person类的实例,即zhangsan是Person类的对象
#调用Person类中的money
print(zhangsan.money) #10000
#调用say_hello这个方法
zhangsan.say_hello() #Hello!
方法的相关知识
- 构造函数:创建对象时,用来完成初始化操作。
其中 self 相当于C++中的 this,并不是关键字,表示当前实例,所有方法中都有这个参数,但调用时不需要指定,通过 self.xxx 访问对象的属性和方法。
def __init__(self,参数2,参数3,...):
pass #占位语句
- 析构函数:清除对象时,回收和释放对象所占资源。
def __del__():
pass
class Person():#声明Person类
#构造函数
def __init__(self,name,age,gender="men"):
#定义属性
self.name=name
self.age=age
self.gender=gender
#析构函数
def __del__(self):
print("Bey bey",self.name)
#成员函数
def printInfo(self):
print("name:",self.name,"age:",self.age,"gender:",self.gender)
zhangsan=Person("zhangsan",18)
lisi=Person("lisi",19,"women")
zhangsan.printInfo() #name: zhangsan age: 18 gender: men
lisi.printInfo() #name: lisi age: 19 gender: women
#调用析构函数
del zhangsan #Bey bey zhangsan
del lisi #Bey bey lisi
- 类方法:可以通过类名或对象调用,不能访问实例属性,可以访问类属性。通过
类名.xxx
调用,调用时不需要传递参数cls
,也可以通过cls.xxx
访问类属性和调用其他类方法。
class 类名:
@classmethod
def 类方法名()
pass
- 静态方法:当不需要访问实例属性或调用实例方法,也不需要访问类属性或调用类方法时,可以把方法封装成一个静态方法,可以通过
类名.xxx
调用静态方法。
class 类名:
@staticmethod
def 类方法名():
pass
下面来看看类方法和静态方法实例:
class Game:
top_score=100
def __init__(self,name):
self.name=name
@staticmethod
def help():
print("Help message...")
@classmethod
def score(cls):
print("最高分:%d"%cls.top_score)
def startGame(self):
print("%s开始游戏!"%self.name)
Game.help() #Help message...
Game.score() #最高分:100
game=Game("RNG Ming")
game.startGame() #RNG Ming开始游戏!
- 成员变量
用下划线作变量名的前缀来指定保护变量和私有变量,Python中没有真正意义的私有(伪私有)。可以用_类名__属性
或者_类名__方法
强制访问私有属性或方法。- 公有变量:可以在类的外部访问;
- 保护变量(_xxx):只允许其本身和子类进行访问;
- 私有变量(__xxx):不允许类的外部访问;
- 专有变量、方法(__xxx__),比如__init__
2. 面向对象的三大特性
封装
封装是对全局作用域中其它区域隐藏多余的信息。比如内部信息不想被外部访问,设为私有变量,函数的私有变量只有内部可以访问,外部不能访问,确保了外部代码不能随意修改对象内部的状态,这样通过访问限制的保护。
class Book:
def __init__(self,name):
self.__name=name#无法从外部访问私有属性实例变量.__name
#想要获取name,增加get_name方法
def get_name(self):
return self.__name
#想要外部修改数据,添加set_name方法
def set_name(self):
return self.__name
继承
子类(派生类)能继承父类(基类)中所有非私有的成员变量和成员函数,有利于代码的复用。
- 单继承和多继承
日常书写中不建议使用多继承,容易简单的东西复杂化。使用多继承的时候,如果两个父类中有相同的方法,尽量避免使用多继承, 避免产生混淆。
class Parent1():
pass
class Parent2():
pass
class Son1(Parent1): #单继承,父类是Parent1,子类是Son1
pass
class Son2(Parent1,Parent2): #多继承,父类是Parent1和Parent2,子类是Son2
pass
- 查看继承
Son1.__bases__ #__base__查看从左到右继承的第一个父类,__bases__查看继承的所有父类
下面看实例:
class Book:
def __init__(self,name,price):
self.name=name
self.price=price
def color(self):
print('颜色!')
class Novel(Book):
def color(self):
print('%s的封面是白色'%self.name)
class Cartoon(Book):
def color(self):
print('%s的封面是彩色'%self.name)
novel=Novel('《霍乱时期的爱情》',55)
cartoon=Cartoon('《妖精的尾巴》',49)
print(novel.name) #《霍乱时期的爱情》
cartoon.color() #《妖精的尾巴》的封面是彩色
- 重写:当父类中的方法不满足需求时,可以在子类中重写父类方法
class Parent:
def myMethod(self):
print("调用父类方法")
class Child(Parent):
def myMethod(self):
print("调用子类方法")
c=Child()
c.myMethod() #调用子类方法
- super()关键字
class NoteBook(Book):
def color(self): #重写方法
super().color() #先调用父类的方法
print("笔记本有不同的颜色!")
多态
多态按字面意思理解就是多种状态,接口的多种不同的实现方式即为多态,也即不同的对象在接收同一条消息时时会执行不同的动作。把不同的子类对象都当作父类来看,可以屏蔽不同子类对象之间的差异。
- “开闭”原则:
对扩展开放:允许子类重写方法函数;
对修改封闭:不重写,直接继承父类方法函数 。
#创建奶茶这个父类,并根据父类创建几个子类
class Milktea:
def make(self):
print("请选择您想要喝的奶茶!")
class Oolong(Milktea):
def make(self):
print("您已选择声声乌龙,正在制作中,请稍后!")
class Coffee(Milktea):
def make(self):
print("您已选择美式咖啡,正在制作中,请稍后!")
#判断用户输入的值并创建相应的对象
class Milktea_make:
@classmethod
def getinput(self,choose):
if choose=="1":
ch=Oolong()
elif choose=="2":
ch=Coffee()
else:
ch=Milktea()
return ch
#通过用户输入的值调用方法
while True:
choose=input("请输入您想要点的奶茶的编号:1.声声乌龙,2.美式咖啡")
if choose=="1" or choose=="2":
ch=Milktea_make.getinput(choose)
ch.make()
break
else:
ch=Milktea()
ch.make()
continue
六、异常
1. 常见异常
异常名称 | 说明 |
---|---|
IOError | 输入/输出异常 |
ImportError | 无法导入模块或包 |
IndentationError | 缩进错误 |
NameError | 没有声明或初始化对象 |
KeyError | 试图访问字典里不存在的键 |
AttributeError | 试图访问一个对象没有的属性 |
TypeError | 类型不匹配 |
ValueError | 传入一个调用者不期望的值,即使值的类型正确 |
2. 异常处理
- try-except语句
try:
语句块
except 异常1 as 错因:
处理代码
except 异常2 as 错因:
处理代码
...
- finally子句:无论异常如何,都将被执行
try:
语句块
except 异常 as 错误原因:
处理代码
finally:
语句块
如下实例中,print(aList[3])
访问列表索引超出范围,程序中断后执行except
中断异常处理代码,try语句块中剩余的代码不再执行。
try:
aList=[0,1,2]
print(aList[3])
print("try语句块继续执行中...")
except IndexError as e:
print(e)
print("异常已经处理!")
finally:
print("无论异常如何finally子句都会被执行!")
print("程序继续执行中...")
输出结果:
list index out of range
异常已经处理!
无论异常如何finally子句都会被执行!
程序继续执行中..
- 异常的传递性
def number():
return int(input("请输入一个数: "))
def extendNum():
number()
try:
extendNum()
except Exception as result:
print("未知错误%s"%result)
异常输出测试:
请输入一个数: p
未知错误invalid literal for int() with base 10: 'p'
raise
抛出异常
类似于Java中的throw关键字。
def inputPassword():
pw=input("请输入密码: ")
if len(pw)>=6:
print("密码输入成功!")
return pw
raise Exception("密码长度小于6...")
try:
inputPassword()
except Exception as result:
print(result)
异常输出测试:
请输入密码: 123
密码长度小于6...
请输入密码: 123456
密码输入成功!
七、文件
文件在计算机中以二进制的方式保存在磁盘上。
- 文本文件:可用文本编辑软件查看,本质上还是二进制文件。如:Python源程序
- 二进制文件:不能用文本编辑软件查看,是供其他软件使用的。如:图片文件
1. 文件路径
- 绝对路径:从盘符开始的路径
比如:C:\Windows\System32\cmd.exe - 相对路径:从当前目录(工作目录)开始的路径
比如:C:\Windows\System32'\cmd.exe'
的后面这部分 - 获取文件当前路径
import os
print(os.getcwd()) #cwd是current working directory的缩写
2. 文件基本操作
函数 | 说明 |
---|---|
open() | 打开文件,如果文件存在则返回文件操作对象,不存在则抛出异常 |
read() | 将文件内容一次性读取到内存并返回文件的所有内容 |
write() | 将指定文本内容写入文件 |
close() | 关闭文件 |
open函数
负责打开文件并返回文件对象;read/write/close方法
要通过文件对象来调用。
#打开文件
file=open("文件路径")
#读取文件
txt=file.read()
print(txt)
#关闭文件
file.close()
访问模式 | 执行操作 |
---|---|
'r' | 以只读方式打开文件(默认),若文件不存在,抛出异常 |
'w' | 以写入方式打开文件,若文件存在会被覆盖,不存在则创建新文件 |
'a' | 以写入方式打开文件,文件指针指向文件末尾,若文件不存在,创建新文件 |
'r+' | 以读写的方式打开文件,文件指针指向文件开头,若文件不存在,抛出异常 |
'w+' | 以读写的方式打开文件,若文件存在会被覆盖,不存在则创建新文件 |
'a+' | 以读写的方式打开文件,文件指针指向文件末尾,若文件不存在,创建新文件 |
'b' | 以二进制模式打开文件 |
't' | 以文本模式打开文件(默认) |
下面是文件的部分操作过程:
#以写的方式打开文件,若无文件myFile则在工作目录下创建该文件
f=open("myFile.txt",'w')
f.write("Python!") #7
f.close
f=open("myFile.txt")
f.read() #'Python!'
f.close()
#以写入的方式打开文件,讲编辑文本添加在末尾
f=open("myFile.txt",'a')
f.write("Hello World!")
f.close()
f=open("myFile.txt")
f.read() #'Python!Hello World!'
f.close()
#以写入方式打开文件,会覆盖已经存在的文件
f=open("myFile.txt",'w')
f.write("python=3.6")
f.close()
f=open("myFile.txt")
f.read() #'python=3.6'
f,close()
3. OS模块命令的使用
在终端/文件浏览器中,可执行常规文件/目录管理操作。例如:创建、重命名、删除、修改路径、查看目录、…在Python中,想要实现这些操作,需要导入os模块
- 文件操作
方法名 | 说明 | 示例 |
---|---|---|
rename | 重命名文件 | os.rename(源文件名, 目标文件名) |
remove | 删除文件 | os.remove(文件名) |
- 目录操作
方法名 | 说明 | 示例 |
---|---|---|
listdir | 目录列表 | os.lisdir(目录名) |
mkdir | 创建目录 | os.mkdir(目录名) |
rmdir | 删除目录 | os.rmdir(目录名) |
getcwd | 获取当前目录 | os.getcwd() |
chdir | 修改工作目录 | os.chdir(目标目录) |
path.isdir | 判断是否是文件 | os.path.isdir(文件路径) |
4. 上下文管理器
弄清除几个概念:
上下文表达式:with open('test.txt') as f:
上下文管理器:open('test.txt')
f不是上下文管理器,而是资源对象
with
关键字:适用于对资源进行访问的场合,确保不管使用过程中是否发生异常都会执行必要的“清理”操作,释放资源。当文件操作执行完成后, with语句会自动调用上下文管理器里的关闭语句来关闭文件资源。
with 上下文管理器表达式 as 变量:
pass
with open("myFile.txt") as f:
print(f.read()) #输出:python=3.6
__enter__
方法:在执行with后面的语句时执行,一般用来处理操作前的内容,如创建对象、初始化等操作。__exit__
方法:在with内的代码执行完毕后执行,一般用来处理一些善后收尾工作,如文件的关闭,数据库的关闭等操作。
class File():
def __init__(self,filename,mode):
print("执行__init__()方法!")
self.filename=filename
self.mode=mode
def __enter__(self):
print("执行__enter__()方法!")
self.f=open(self.filename,self.mode)
return self.f
def __exit__(self,*args):
print("执行__exit__()方法!")
self.f.close()
with File('test.txt','a+') as f:
f.write("Hello Python!!!")
print("文件写入成功!")
输出结果:
执行__init__()方法!
执行__enter__()方法!
文件写入成功!
执行__exit__()方法!
__exit__
方法中有三个参数,用来接收处理异常,代码在运行时发生异常,异常会被保存在参数中:exc_type
: 异常类型,exc_val
: 异常值,exc_tb
: 异常回溯追踪
class Div():
def __init__(self,x,y):
self.x=x
self.y=y
def __enter__(self):
print("执行到了__enter__()方法!")
return self
def __exit__(self,exc_type,exc_val,exc_tb):
print("执行到了__exit__()方法!")
if exc_type==None:
print("No problem!")
else:
print("Error!程序问题如下:")
print("Type",exc_type)
print("Value:",exc_val)
print("TraceBack:",exc_tb)
#返回值决定了捕获的异常是否继续向外抛出,
#如果是False那么就会继续向外抛出,程序会看到系统提示的异常信息
#如果是True不会向外抛出,程序看不到系统提示信息,只能看到else中的输出
return True
def div(self):
print("执行到了除法div!")
return self.x/self.y
with Div(1,0) as mc:
mc.div()
输出结果如下:
执行到了__enter__()方法!
执行到了除法div!
执行到了__exit__()方法!
Error!程序问题如下:
Type <class 'ZeroDivisionError'>
Value: division by zero
TraceBack: <traceback object at 0x000002120B98A708>