python

作者

prometheus-code

这篇笔记只是为了方便查阅,并非为实用教程

基本语法

  1. 在Python中严格区分大小写
  2. Python中的每一行就是一条语句,每条语句以换行结束
  3. Python中每一行语句不要太长
  4. 一条语句可以分多行编写,语句后边以\结尾
  5. Python是缩进严格的语言,所以在Python中不要随便写缩进
  6. 在python中使用#表示注释

字符

字符串

  1. 单双引号不能欢行
  2. 三重引号可以换行“ ” “
    • \t 制表
    • \n 换行
  3. 方法
    • split方法

字符串只能和字符串拼接

格式化字符串

1
2
3
c=f‘hello {a} {b}’
print("123,%d,%d"%(123,123))
print(f'hello {a} {b}')
1
2
3
4
5
a=123
print('a=%d,a=%d'%(a,a))
print(f"a={a}")
print('a='+str(a))
print('a=',a)

字符串的复制

字符串和数字相乘

布尔值(bool)和空值

  1. bool:True和False

  2. None(空值)

    1
    a=None

类型检查

  1. type()检查值的类型

对象id

id()


算术运算符

  1. 加减乘除
  2. / 除法,返回一个浮点类型
  3. // 整除,返回一个整型
  4. ** 幂运算,求一个值的几次幂
  5. % 取模,求余数

赋值运算符

  1. +=
  2. -=
  3. *=
  4. **=
  5. /=
  6. //=
  7. %=

关系运算符

返回布尔值

大于小于等于

不等于 !=


逻辑运算符

not

and

or

  • 针对非布尔值的运算
    • and 当True时,取值看最后一个True的值
    • or 当True时,取值看第一个True的值

理解:看逻辑运算找那个值的布尔值


条件运算符

语法:语句1 if 条件表达式 else 语句2

1
2
print('1')if True else print('0')
max=a if (a>b and a>c) else (b if b>0 else c)

运算符的优先级

  • 逻辑运算优先级 not高and高or
  • 查表

条件判断句

  1. 语法:if 条件表达式 :语句
  2. if elif else
  3. python里没有switch语句,但可以通过if语句或字典来实现类似功能

序列

列表

1
2
3
my_list=[]
my_list[0] #索引第一个元素
len(my_list) #获取列表长度=最大索引下标+1

列表切片

从现有列表中获取子列表

索引可以是负数,表示倒数第几个

语法:列表[起始:结束:步长]

与matlab不同的地方,一般步长省略,步长可以是负数

通过切片获取元素时,会包括起始元素位置的元素,不会包含结束位置的元素

就是从第几个元素(这里指从0号开始计算的元素)开始数到第几个位置(这里是从1开始数的位置)

省前不省后,从第一个截取

省后不省前,一直截取到最后

全省则取全部元素

一般用于用步长取特定间隔的元素

1
2
3
4
5
stu=[1,2,3]
st=stu[0:3]
print(stu[0:])
print(stu[0:2])
print(st[::-1]) #倒序输出

基本列表操作

  • in 和not in

    检查元素存在与否,返回布尔值

  • len()获取列表中元素个数

  • min()

  • max()

  • 方法

    • index(x,y,z) 获取列表中元素第一次出现的索引

      • x表示被找元素
      • y表示起始元素的位置(从0开始数)
      • z表示结束位置(这里从1开始数)
      1
      2
      my_list=[1,2,3]
      my_list.index('2') %返回
    • count()列表中元素出现次数


序列(sequence)


操作列表

  • 方法

    • append()

      向列表的最后添加一个元素

    • insert()

      1.要插入的位置

      2.要插入的元素

    • extend()

      用一个新列表来扩展当前列表

    • clear()

      清空序列

    • pop()

      根据索引删除并返回被删除元素

    • remove()

      删除指定值的元素

    • reverse()

      翻转列表

    • sort()

      自动排序,默认升序排列

      sort(reverse=True)降序排序

    for循环

    for 变量 in 序列:

    ​ 代码块

    for循环次数,循环次数为列表元素个数

    range():

        1. 起始位置(可以省略,默认是0)
          2. 结束位置
                        3. 步长(可以省略,默认是1)
    

元组

用()来创造元组

1
2
my_tuple= 10,20,30,40 #或者my_tuple= (10,20,30,40)
a,b,c,d=my_tuple #将元组里的元素分别赋给变量

也可以利用元组解包交换值

1
a,b=b,a #等号右边相当于一个元组

对一个元组进行解包时,变量数量必须于元组中元素的数量一直,或则在一个变量前加*,将变量变成列表获取元组中所有的剩余元素

1
2
3
4
my_tuple=(1,2,3,4,5,6)
a,b,*C=my_tuple
a,*b,c=my_tuple
*a,b,c=my_tuple

所有序列都可以用元组的方法解包

不能出现两个及以上的*变量


可变对象

  • 每个对象中含有三个部分:id(标识),type(类型),value(值)
  • 对象只能改变值,且只有可变对象可改变

  • is 和 is not 比较对象id是否一致
  • ==和!=比较对象的值是否一致

字典

  • 字典属于一种新的数据结构,称为映射(mapping)

  • 字典的作用与列表类似,都是用来存储对象的容器

  • 列表存储数据的性能很好,但是查询数据的性能很差

  • 在字典中每一个元素都有唯一的名字,通过这个唯一的名字可以快速查找指定的元素

  • 字典可以保存多个对象,每个对象都会有一个唯一的名字

    • 这个唯一的名字,我们称其为键(key),通过key可以快速查询value

    • 这个对象,我们称其为值(value)

      • 字典的值可以是任意对象
      • 字典的键可以说任意的不可变对象(int,str,bool,tuple…)

      字典的键是不能重复的,如果后面出现重复的后边的会替换到前边的

    1
    2
    3
    4
    5
    d={
    'name''zhangsan',
    'age':18,
    'sex':'man'
    }

  • 可以使用dict()函数来创造字典

  • 可以将双值子序列的序列转换为字典

  • 函数

    • len() 获取字典中键值对的个数
    • in 检查字典中是否包含指定的键
    • not in 同上
  • 获取字典中的值,根据键来获取值

    语法:d[key]

    但用[ ]来获取值时,如果键不存在,会抛出异常

  • 方法

    • get() 该方法用来根据键来获取字典中的值

      • 也可以指定默认值来作为获取不到时的返回值
    • setdefault(key[,default])
      • 如果key已经存在于字典中,则会返回key的值不会对字典做任何操作
      • 如果key不存在,则添加这个键对
    • update()

      • 添加一个字典合并成新字典,如果有重复的键则会用后面的值替换前面的值
    • popitem()
      • 随机删除字典中的一个键值对,一般都会删除最后一个键值对
      • 删除之后,它会将键值对作为返回值返回
      • 返回的是一个元组,元组中有两个元素,第一个元素是删除的key,第二个是删除的value
      • 当空的时候会抛出异常
    • pop(key[,default])
      • 根据key删除字典中的key-value
      • 会将被删除的value返回
      • 如果删除不存在的key,会异常
      • 如果写了默认值,则会在异常时返回默认值r
    • clear()
    • copy()
      • 浅复制,不能对对象中的对象进行copy
      • 因为直接等于只是同一个对象
      • 但copy只可以复制对象里的值,创建一个新对象
  • del删除键
1
del d['a']
  • 遍历

    • .keys()

      • 该方法会返回字典的所有的key
      • 返回的格式是序列
      1
      2
      3
      for k in d.keys():
      print(k)
      print(d[k])
  • .values()

    • 该方法会返回序列含有字典的所有的值
  • items()

    • 该方法会返回字典中的所有项
    • 返回一个序列,序列中包含双值子序列

集合

  • 集合和列表非常相似

  • 不同点:

    • 集合中只能存储不可变对象(元组,等)
    • 集合中存储的对象是无序(不是按照元素的插入顺序来排列的)
    • 元素唯一性
  • 使用{ }来创建集合

    1
    s={2,1,4,3}
  • 用set( )来创建集合

    • 可以通过set( )来将序列和字典变成集合
  • 可以使用in和not in

  • len()

  • 方法

    • add( )向集合中添加元素
    • update( )向集合中添加元素
    • pop( )随机删除集合中元素
    • remove( )删除集合中的指定元素
    • clear( )
    • copy( )
  • 运算

    1
    2
    s={1,2,3,4,5}
    s2={3,4,5,6,7}
    • 交集运算

      1
      s & s2 #作为表示式 {3,4,5}
    • 并集运算

      1
      s | s2 # {1,2,3,4,5,6,7}
    • 差集运算

      1
      s - s2 # {1,2} 在s中s2没有的元素
    • 亦或集

      1
      s ^s2 # {1,2,6,7} 获取只在一个集合中出现的元素
    • <= 检查一个集合是否是另一个元素的子集

      1
      2
      3
      a={1,2,3}
      b={1,2,3,4,5}
      print(a<=b) #result is True
    • < 检查一个集合是否是另一个子集的真子集

    • > =

    • >


函数

语法:

1
def fn(a=1,b,c): #可以给形参赋默认值,但如果实参被传入则看实参的值

位置参数和关键字参数可以混合使用

关键字参数一般有默认值

但位置参数的顺序不能颠倒

传可变对象在函数内修改也会对同一个对象进行修改

所以可以使用对象的副本如 c.copy()

  • 不定长参数:*a

    • 定义函数时可以在形参前面加*,这样这个形参将会获取所有的实参并保存到一个元组中

    例子:

    1
    2
    3
    4
    5
    def sum(*a):
    result=0
    for x in a:
    result+=x
    print('a=',a,type(a))

    不定长参数:

    参数装包:

    • 带一个星号的形参(*x)

      • 但可以与其他参数混用
      • 且星号后的所有参书

      • 不能接受关键字参数

      • 只能有一个
    • 带两个星号的参数(**x)

      • 可以接收其他的关键字参数
      • 它会将这些参数统一保存在一个字典中
      • 且必须写在所有参数的后面
      • 只能有一个

    参数解包:

    • 传递实参时,也可以在序列类型的参数前添加星号,这样他会自动将序列中的元素依次作为参数传递
    • 这里要求双方个数统一
    • *x 可以传递元组
    • **x 可以传递字典

    返回值:

    • return

      1
      2
      3
      4
      5
      def fn():
      #代码块
      return #数值或函数
      #如果没写ruturn或没接返回值,则为返回None
      #return 会结束函数
    • fn和fn( )的区别

      • fn是函数对象
      • fn( )是fn( )的返回值
  • 文档字符串

    • help( )

      python中的内置函数

      可以查询python中的函数的用法

    • 文档字符串写函数说明

      • 在定义函数时,可以在函数内部编写文档字符串,文档字符串就是函数的说明
      • 当函数有文档字符串时,可以用help查看用法
1
2
3
4
5
6
7
8
9
10
11
12
13
14
def fn(a:int,b:bool,c:str): #用 : 描述函数参数的类型
'''
这是文档字符串的示例
函数的作用:。。。
函数的参数:
a,作用,类型,默认值。。。
b,作用,类型,默认值。。。
c,作用,类型,默认值。。。
'''
#代码块
return #数值或函数
#如果没写ruturn或没接返回值,则为返回None
#return 会结束函数
help(fn)
  • 作用域
    • 全局作用域
    • 函数作用域
    • 变量会优先在当前作用域中寻找
    • 或者用global声明全局变量
    • 命名空间
      • 本质是字典
      • 用local( )函数获取作用域的命名空间(字典)
      • 用globals( )可以获取全局命名空间

函数式编程

  • 高阶函数

    • 可以接受一个或多个函数作为参数
      • 把函数当判断语句用
      • 将函数作为返回值返回
  • filter( )

    过滤器
    可以从序列中过滤除符合条件的元素,保存到一个可迭代的数据结中

    • 参数:
      • 函数,根据该函数来过滤
      • 需要过滤的可迭代数据结构
    • 返回值:
      • 过滤后的可迭代的数据结构
    • 理解性代码(不实用)
    1
    2
    3
    4
    5
    6
    7
    8
    9
    def fn2(i):
    if i%2 == 0:
    return True
    return False
    # def fn2(i):
    # return i%2==0
    l=[1,2,3,4,5,6,7]
    result=filter(fn2,l)
    print(list(result))
  • map( )

    可以对可迭代对象中的元素做指定操作,然后将其添加到一个新的对象中返回

    1
    2
    l=[1,2,3,4,5,6,7]
    r=map(lambda i:i+5,l)
  • sort( )

    该方法用来对列表中的元素进行排序

    也可以把函数作为参数,当作排序条件

    • 在sort( )可以接受一个关键字参数,key
    • key需要一个函数作为参数,当设置了函数作为参数,每次都会以列表中的一个元素组偶我参数来调用函数,并且使用函数的返回值来比较元素的大小
    1
    2
    3
    4
    5
    l=['bb','aaaa','c','dddddd','fff']
    l.sort(key=len)
    l1=[2,5,'1',3,'6','4']
    l1.sort(key=str)
    l1.sort(key=int)
  • sorted( )

    这个函数和sort( )的用法基本一致,但是sorted( )可以对任意的序列进行排序 , 并且使用sorted( )排序不会影响原来的对象,而是返回一个新对象.

    • !!! 深度复制
  • 匿名函数

    • 匿名函数一般作为参数使用
    • lambda函数表达式专门用来创造一些简单的函数,函数创造的又一种方法
    • 语法: lambda 参数列表:返回值
    1
    2
    3
    lambda a,b : a+b #调用函数
    (lambda a,b:a+b)(10,20)#一种赋值方法
    f=lambda c,d : c+d
    1
    lambda i:i>5
  • 闭包

    • 可以通过闭包创建一些只有当前函数能访问的变量
    1
    2
    3
    4
    5
    6
    def make_averager():
    nums=[]
    def averager(n):
    num.append(n)
    return sum(nums)/len(nums)
    return averager
    • 形成闭包的必要条件
      • 函数嵌套
      • 将内部函数作为返回值返回
      • 内部函数必须要使用到外部函数的变量
  • 装饰器

    扩展函数的功能

  • 代码

    1
    2
    3
    4
    5
    6
    7
    def begin_end(old):
    def new_function(*args,**kwargs):
    print('begin')
    result=old(*args,**kwargs)
    print('end')
    return result
    return new_function

    使用装饰器

    在定义函数时可以使用@装饰器,来使用指定的装饰器

    多个装饰器时,按照从内到外的顺序定义

    1
    2
    3
    @begin_end #使用装饰器
    def say_hello():
    print('hello')

面向对象

  • 找对象
  • 搞它

类(class)

  • 自定义对象
  • 类是对象的图纸,对象是类的实例
  • 如果多个对象是通过一个类创建的,我们称这些对象是一类对象
  • 像int( ),float( ),bool( ),list( ),dict( )…这些都是类
  • a=int(10)#创建一个int( )类的实例,等价于a=10
  • 我们自定义的类都需要使用大写字母开头,如用大驼峰命名法

自定义类

类也是一个对象

  • 类创建对象的简要流程:

    • 创建一个变量mc
    • 在内存中创建一个新对象
    • 将对象的id赋值给变量
  • class 类名([父类]):

    1
    2
    class Myclass():
    pass

    使用类来创建对象,就像调用一个函数一样的语法

    1
    2
    mc = Myclass( )
    print(type(mc))
  • isinstance( )函数可以用来检查一个对象是否是一个类的实例

  • 对象中的变量称之为属性

    1
    mc.name='sucker' #mc对象中name变量被赋值'suceker'

类的定义

类和对象都是对现实生活中或程序中的内容的抽象

实际上所有的事物都是由两部分构成:

  1. 数据(属性)
  2. 行为(方法)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# 尝试定义一个表示人的类
class Person:
# 在类的代码块中,我们可以定义变量和函数
# 在类中我们所定义的变量,将会成为所有的实例的公共属性
# 所有实例都可以访问这些变量
name='swk' # 公告属性,所有实例都可以访问

# 在类中也可以定义函数,类中的定义的函数,我们称为方法
# 这些方法可以通过该类的所有实例来访问
def say_hello(self):
print('hello')

#调用方法,对象.方法名()
#方法调用和函数调用的区别
#如果是函数调用,则调用时传几个参数,就会有几个参数
#但是如果是方法调用,解析器会默认传递一个参数,所以方法中至少要定义一个形参
p1=Person()
p1.say_hello()
  • 当我们调用一个对象的属性时,解析器会先在当前对象中寻找是否含有该属性,如果有则会直接返回,如果没有则会在类对象中寻找属性,如果还没有则报错
1
2
p1=Person()
p1.name #先找自己对象,后找在类中找

如果这个属性(方法)是所有的实例共享,则应该将其保存在类对象中

反之则保存在实例对象中

  • 一般情况下,属性保存在实例当中,方法保存在类中

方法不能直接访问类中的属性

  • 方法默认第一个参数,就是调用方法的对象本身

  • 在类中可以定义一些特殊的方法(魔术方法)

    特殊方法都是以_开头,__结尾的方法

    特殊方法不需要我们自己调用,它会在特殊时刻自我调用,所以不推荐手动调用特殊方法


类创建对象的过程:

  1. 创建一个变量
  2. 在内存中创建一个新对象
  3. _init__(self)方法执行
  4. 将对象的id赋值给变量

调用类对象时,实参会依次赋值给形参

类的基本结构:

1
2
3
4
5
6
7
8
9
class 类名([父类]):
公共属性...
#对象的初始化方法
def __init__(self,...):
...
#其他的方法
def method_1(self,..):
...
...

封包

  1. 隐藏了属性名,保证了安全
  2. 又保证了可修改属性的读取和设置
  • 如何隐藏一个对象的属性?

    将对象的属性名,修改为一个外部不知道的名字

  • 如何获取(修改)对象中的属性?

    需要提供一个getter和setter方法使外部可以访问到属性

    • get方法代码格式

      1
      2
      def get_name(self):
      return self.hidden_name
    • set方法代码格式

      1
      2
      def set_name(self,name):
      self.name=name

下划线(双下划线)类名会被python自动为属性改了名字 (一般不用这方法)

1
__name-->_Person_name

  • 一般我们会将一些私有属性(不希望被外部访问的属性)以_开头
  • 一般情况下,使用_开头的属性都是私有属性,没有特殊需求不要修改私有属性

property修饰器

get方法修饰器

@property修饰器修饰的函数名.setter修饰器

set方法修饰器

1
2
3
4
5
6
7
8
9
class cl():
def __init__(self,name):
self._name=name
@property #property修饰器
def name(self):
return self._name
@name.setter #必须与property修饰的函数名相同
def name(self,name):
self._name=name

继承:

  • 语法:class 类名(父类)
  • 继承父类中的属性和方法

  • 可以在当前类中重写方法
  • 可以用super( )在子类中调用父类方法
1
#__base__  这个属性可以用来获取当前类的所有父类
  • 多重继承,会使子类同时拥有多个父类
  • 一般不推荐使用多重继承
  • 考虑父类顺序时,按传入时间顺序判断
  • 开发中没有特殊情况,应避免使用多重继承

多态

针对函数来说

函数可以传不同对象的相同属性

针对性弱,通用性强

1
2
def say_hello(obj):
print('hello %s'%obj.name)
  • 对于say_hello( )这个函数来说,只要对象中含有name属性,它就可以作为参数传递
  • 这就是一个多态,多个不同类型对象的同一个属性的不同表现

如果像以下代码实现,则不是多态

1
2
3
4
def say_hello(obj):
# 做类型检查,针对性强,通用性弱
if isinstance(obj,A)
print('hello %s'%obj.name)

鸭子类型

如果一个东西,走路像鸭子,叫声像鸭子,那么它就是鸭子


len( )

之所以一个对象能通过len( )来获取长度,是因为对象中有一个特殊方法(双下划线)len(双下划线),就可以通过len( )来获取它的长度


面对对象的三大特征

  • 封装

    保证了对象中的数据安全

  • 继承

    保证了对象的可扩展性

  • 多态

    保证了程序的灵活性

类的属性和方法总结

1
2
3
4
5
6
7
# 定义一个类
class A(object):
# 类属性,在类中直接定义的属性是类属性
# 类属性可以通过类或类的实例访问到
count = 0
#类属性只能通过类对象来修改,无法通过实例对象修改
#类对象只能创造一个同名属性来覆盖原来从访问得到的类属性
  • 属性

    • 类属性

      类属性可以通过类或类的实例访问到

      类属性只能通过类对象来修改,无法通过实例对象修改

    • 实例属性

      实例属性只能实例自己能访问和修改

  • 方法

    • 实例方法
      • 在类中定义,以self为第一个参数的方法都是实例方法
      • 实例方法在调用是,python会将调用对象作为self传入
        • 当通过实例调用时,会自动将当前调用对象作为self传入
        • 当通过类调用时,不会自动传递self,此时我们必须手动传递self。
    • 类方法
      • 在类内部使用@classmethod来修饰的方法属于类方法
      • 类方法的第一个参数cls,也会被自动传递,此时的cls就是当前的类对象
    • 区别
      • 实例方法的第一个对象就是self,而类方法的第一个参数是cls
    • 相同点
      • 类方法也可以通过类去调用,也可以通过实例调用,没有区别
    • 静态方法(代码伪装,工具包)
      • 在类中使用@staticmethod 来修饰的方法属于静态方法
      • 静态方法不需要指定任何的默认参数,静态方法可以通过类和实例去调用
      • 静态方法,基本上是一个和当前类无关的方法,它只是一个保存到当前类中的函数

  • 类属性
  • 实例属性
  • 实例方法
  • 静态方法

垃圾回收


1
2
3
4
5
6
7
8
9
10
11
class A:
def __init__ (self):
self.name='A'
def __del__(self): #__del__方法,会在对象被垃圾回收前调用
print('A is delled')
a=A()
# 被变量应用后,对象被'激活'
#但当'激活'后的对象没有任何变量引用后就变成垃圾
#如以下
a=None #此时没有任何变量引用A对象,A对象变成垃圾
#或者用del a

特殊方法(魔术方法)


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#特殊方法都是使用__开头和结尾的
#特殊方法一般不需要我们手动调用,需要在一些特殊时刻调用

#__str__()这个特殊方法会在尝试将对象转换为字符串时调用
#作用:它可以用来指定对象转换为字符串的结果

#__repr__()这个特殊方法会在对当前对象使用repr()函数时调用
#repr()的作用是指定对象在'交互模式'中直接输出的效果

#__lt__()小于 <
#__le__()小于等于 <=
#__eq__()等于 ==
#__ne__()不等于 !=
#__gt__()大于 >
#__ge__()大于等于 >=
#这类比较型的方法需要两个形参
def __lt__(self,other):
return self.age<self.age

#__len__()在使用len()函数时调用

#__bool__()在使用bool()函数时调用,或者在判断语句中自动转bool值时调用

模块


  • 模块化,模块化指将一个完整的程序分解为一个一个小的模块

  • 通过模块组合,来搭建出一个完整的程序

  • 不采用模块化,统一将所有的代码编写到一个文件中

  • 采用模块化,将程序分别编写到多个文件中

  • 在python中一个py文件就是一个模块

    模块名要标识符的规范

  • 优点:

    • 方便开发
    • 方便维护
    • 模块可以复用

import 模块名(模块名,就是python文件的名字,注意不要py)

import可以在程序的任意位置调用,(一般推荐开头调用)

1
2
3
#在每一个模块内部都有一个__name__属性,通过这个属性可以获得模块的名字
#__name__属性值为__main__的模块是主模块,一个程序中只会有一个主模块
#主模块就是我们通过python执行的模块

模块的使用


  • 访问模块中的变量: 模块名.变量名
  • 也可以在模块中定义函数,同样可以通过模块访问到
  • 也可以定义类

可以通过 import 模块名 引用模块 as 别名

也可以通过 from 模块名 import 要引入的代码块 as 别名

from 模块名 import * 引入模块中的所有内容(不建议使用)

  • 模块的变量隐藏

    在变量名中加一个下划线

    在import *时不会被其他程序访问到,其他情况可以访问到

  • 模块的测试方法

    • 只要当前文件作为主模块的时候才需要执行

      1
      2
      if __name__==__main__:
      # 测试测试代码

  • 总结引入方法
    • import xxx
    • import xxx as yyy
    • form xxx import yyy , zzz , fff
    • from xxx import *

包 package

  • 包是一个特殊的模块,包是文件夹

  • 当我们模块中代码过多时,或者一个模块需要被分解成为多个模块时,这时就需要使用到包,普通的模块就是一个py文件,而包是一个文件夹

    1
    # 包中必须要有一个__init__.py 这个文件,这个文件可以包含包中的主要内容
    1
    2
    3
    4
    # __pycache__是模块的缓存文件
    #py代码在执行前,需要被解析器先转换成机器码然后再交由计算机执行
    #而为了提供程序运行的效率,python会再编译过一次以后,将代码保存到一个缓存文件中
    #这样以后加载这个模块(包)时,就可以不再直接加载缓存中编译好的代码

python标准库


  • pprint库

    • pprint.pprint
      • 格式化要打印的内容
  • sys库

    • sys.argv

      • 获取执行代码时,命令行中所包含的参数
      • 该属性是一个列表,列表中保存了当前命令的所有参数
      1
      print(sys.argv)
    • sys.modules

      • 获取当前程序中引入的所有模块
      • modules是一个字典,字典的key是模块的名字,字典的value是模块对象
    • sys.path

      • 它是一个列表,列表中保存的是模块的搜索路径
    • sys.platform

      • 表示当前python运行的平台
    • sys.exit( )

      • 这个函数用来退出程序
      • 也可以把一些字符串当参数传入

        1
        sys.exit('end')
  • os库 (operating system)

    使我们可以对操作系统进行操作

    • os.environ
      • 通过这个属性可以获取到系统的环境变量
    • os.system( )
      • 可以用来执行操作系统的命令
      • 比如Dos指令

异常和文件

异常

  • 程序在运行过程当中,不可避免的出现了一些错误,比如

    • 使用了没有赋值过的变量
    • 使用了不存在的索引
    • 算法错误
      • 异常会使程序立刻终止,使异常以后的代码都不会执行
  • 处理异常

    • try语句

      • 用来测试可能出错的语句
      1
      2
      3
      4
      5
      6
      7
      8
      try:
      #代码块(可能出错误的语句)
      expect 异常类型 as 异常名:
      #代码块(出错后的处理方式)
      else:#基本没有
      #代码块(没出错时的语句)
      finally:
      #代码块(该语句都会执行)
    • 可以将可能出错的代码放入try语句,这样如果代码没有问题,则会正常执行,如果出现错误,则会执行expect子句中的代码,这样我们就可以通过代码来处理异常
    • 避免因为一个异常导致整个程序的终止
  • 异常的传播 (抛出异常)

    • 当函数中出现异常时,如果在函数中对异常进行了处理,则异常不会再继续传播,如果函数中没有对异常进行处理,则异常会继续向函数调用处传播,再往全局作用域(主模块) , 如果异常依然没有处理 , 则程序终止 ,

      显示异常信息

    • 当程序运行中出现异常以后,所有的异常信息会被保存再一个专门的异常对象中,而异常传播时,实际上就是异常对象抛给了调用处

      比如:

      • ZeroDivisionerror类的对象专门用来表示除0的异常
      • NameError类的对象专门用来处理变量错误的异常

        ​ …


  • 如果except后不跟任何内容,则此时它会捕获到所有的异常
    • 如果跟指定的异常类型,则只会捕获指定异常类型
    • 不跟任何异常类型等于接个Exception(所有异常类的父类),也会捕获所有异常
1
2
3
4
5
6
7
8
9
10
11
try:
print(c)
print(10/0)
except NameError:#捕获特定的异常类型NameError
print('NameError')
except ZeroDivisionError as e:#用e来引用ZeroDivisionError异常类,来查看异常
print('ZeroDivisionError')
except:
print('unknown',e)
finally :#无论是否出现异常该子句都会执行
print('finally')
  • 可以在异常类后面跟着一个 as xx 此时xx就是异常对象

总结:

try必写,finally和except必写一个


抛出异常(自定义异常提示)

好处,可以将异常提示联系到实际问题中

  • 用raise语句来抛出异常

    • raise语句后面需要跟一个异常类 或 异常的实例

      1
      2
      3
      4
      5
      6
      def add(a,b):
      if a<0 or b<0:
      raise Exception('两个参数中不能有负数!')
      r = a+b
      return r
      print(add(-123,456))
  • 也可以自定义异常类。只需要创建一个类继承Exception

    1
    2
    3
    4
    5
    6
    7
    8
    class MyError(Exception):
    pass
    def add(a,b):
    if a<0 or b<0:
    raise MyError('两个参数中不能有负数!')
    r = a+b
    return r
    print(add(-123,456))

文件

  • 操作文件的步骤

    • 打开文件
    • 对文件进行各种操纵(读,写),然后保存
    • 关闭文件
  • 打开文件的函数

    open(file,mode=’r’,buffering=-1,encoding=None,errors=None,newline=None,closefd=True)

    • 使用open函数来打开一个文件

    • 参数:

      • file 要打开的文件的名字(路径)

        在windows系统使用路径时,可以使用/来代替\

        或者可以使用原始字符串

        在字符串前加r

        如: r’hello\demo.txt’

        表示路径时,可以使用..来返回一级目录

        以下为建立路径所使用的几个特殊符号,及其所代表的意义。

        “./”:代表目前所在的目录。

        “../”:代表上一层目录。

        以”/”开头:代表根目录。

        file_name=r’..\hello\demo.txt’

        如果目标文件距离当前文件比较远,可以使用绝对路径

    • 返回值

      • 返回一个对象,这个对象就代表了当前打开的文件
  • 文件对象

    • read()方法,用来读取文件中的内容,它会将内容全部保存为一个字符串返回
    • close()方法,用来关闭文件
  • with … as 语句

    • 在with语句中可以直接使用as赋值后的变量名来做文件操作
    • 此时这个文件只能在with中使用,一旦with接受则文件会自动close()

      1
      2
      with open(file_name) as file_obj:
      print(file_obj.read)
  • 文件操作基本格式

    1
    2
    3
    4
    5
    try:
    with open(file_name) as file_name:
    print(file_obj.read)
    except FileNotFoundError:
    print(f'{file_name}is not found')

文件的读取

  • open函数打开文件时,默认为None编码,为了正常读取文件,推荐用unicode编码,如

    1
    open(file_name,encoding='utf-8')
  • read( )会默认读取文件的所有内容,会一次性将文件的内容加载到内存中,容易导致内存泄漏

    • read( )可以接受一个size作为参数,该参数决定每次读取的字符的数量
    • 默认值为-1,默认读取所有内容
    • 可以为size指定一个值,这样read( )会读取指定数量的字符
    • 每一次读取都是从上次读取到位置开始读取的
      • 如果字符的数量小于size,则会读取剩余所有的
      • 如果已经读取到文件的最后了,则会返回’ ‘字符
  • 读取大文件的方法

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    try:
    with open(file_name,encoding='utf-8') as file_obj:
    #定义一个变量,来保存文件的内容
    file_content=' '
    #定义一个变量,来指定每次读取的大小
    chunk = 100
    #创造一个循环来读取文件内容
    while True:
    content = file_obj.read(chunk)
    #检查是否读取到了内容
    if not content:#当content读取到空值时
    print('\nthe file is ended')
    break
    file_content += content
    except FileNotFoundError:
    print(f'{file_name} is not found')

  • readline( )方法
    • 该方法可以读取一行的内容
  • readlines( )方法
    • 该方法也是一行一行读取内容,它会一次性将读取到的内容封装到一个列表中返回
    • 列表中一行数据为一个元素
  • 也可以直接用for循环迭代读取文件

文件的写入


  • 使用open( )打开文件时必须先要指定打开文件所要做的操作(读,写,追加)
  • 如果不指定操作类型,则默认是读取文件,而读取文件时是不能向文件中写入的

r 表示只读的

w 表示文件是可写的,使用w来写入文件时,如果文件不存在会创造文件,如果文件存在则会截断文件。

截断文件表示删除原来文件中的所有内容

a 表示追加内容,如果文件不存在会创造,如果文件存在则会向文件中追加内容

x 用来新建文件,文件如果存在则报错

+为操作符增加功能

r+ 即可读可写,但文件不存在会报错

w+

a+


  • write( )来向文件中写入内容
  • 如果操作的是一个文本文件的话,则write需要传递一个字符串作为参数
  • 该方法可以分多次向文件中写入内容
  • 写入完成以后,该方法会返回写入的字符的个数

二进制文件

  • 除文本文件外的文件都可以认为是二进制文件

  • 读取模式

    • t 读取文本文件(默认)
    • b 读取二进制文件

      如: rb, wb,

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
with open(file_name,'rb') as file_obj:
#读取文本文件时,size是以字符为单位的
#读取二进制文件时,size是以字节为单位
#print(file_naem.obj(100))

#将读取到的内容写出来
#定义一个新的文件
new_name='aa.flac'
with open(new_name,'wb') as new_obj:
#定义每次读取的大小
chunk=1024*100
#从已有的对象中读取数据
wile True:
content= file_obj.read(chunk)

if not content:
break
# 将读取到的数据写入到新对象中
new_obj.write(content)

读取文件的位置

针对字节位置来考虑

  • tell( )方法用来查看当前读取到的位置

  • seek( )可以修改当前读取的位置

    • 需要两个参数

      • 第一个 是要切换到的位置

      • 第二个 计算方式

        • 可选值

          0 从头计算,默认值

          1 从当前位置计算

          2 从最后位置计算

文件的其他操作


os库

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
import os
from pprint import pprint
# os.listdir()会获取当前目录结构
# 需要一个路径作为参数,会获取到该路径下的目录结构,默认路径为 . 当前目录
# 该方法会返回一个列表,目录中的每一个文件(夹)的明治都是列表中的一个元素
r = os.listdir()

# os.getcwd() 获取当前的目录

#os.chdir() 切换当前所在的目录 作用相对于 cd

# 创建目录
#os.mkdir('abc')

#删除目录
#os.rmdir('abc')

#删除文件
#os.remove('abc.txt')

#重命名 同时也可以对一个文件进行移动,
#os.rename('旧名字','新名字')

pprint(r)