Python基础阶段重点知识总结
注释
- 单行注释 --> #注释内容
- 多行注释 --> “”“注释内容”"" 或 ‘’‘注释内容’’’
变量
- 变量的作用:用来存储数据的一种形式
- 变量的定义:字母、数字、下划线且数字不能开头
- 变量的类型:int float str list dict tuple bool
输出
- 格式化输出:%s %d %f
- %d: 要输出n位数字,前面以0补位 —> print("%06d" % 1) 000001
- %f:保留两位有效数字 —>print("%.2f" % 0.1) 0.10
- %%:输出0.10% —> print("%.2f%%" % 0.1)
输入
- input输入:
- 在python2中,raw_input(“提示信息”) 都作为字符串对待,input()函数则接受表达式输入
- 在python3中,只有input函数,与python2中raw_input(“提示信息”)一致
流程控制
运算符
- 算术运算符:+ - * / //(取整除) %取余 **指数
注意:混合运算时,优先级顺序为:
**
高于*
/
%
//
高于+
-
,为了避免歧义,建议使用()
来处理运算符优先级。
- 赋值运算符 =
- 复合运算符 += -= *= /= %= //= **=
数据类型转换
- 常见的数据类型转换 int() float() str()
判断语句
-
if 条件语句
-
if … else …
-
if … elif … elif … else …
-
if 嵌套
-
if 三目运算 demo: a if a<b else b
循环语句
- while循环语句格式
- while循环嵌套 (重难点) demo:九九乘法表
- for循环遍历
for 临时变量 in 列表或者字符串等可迭代对象: 循环满足条件时执行的代码
-
break和continue的区别
- break直接结束循环
- continue结束本次循环,执行下一次循环
- 注意:break和continue都只对最近的一层循环起作用
-
break和continue在循环嵌套中的区别(详见代码)
def func1(): for i in "abcde": for j in "fghijk": if j == "h": break print(j) print(i) func1() def func2(): for i in "abcde": for j in "fghijk": if j == "h": continue print(j) print(i) func2()
容器类型
字符串
-
定义格式:两单引号’abc’,两双引号"abc",两三引号""“abc”""
-
下标和切片:
- 通过下标获取字符串中的元素
- 下标起始从0开始,最后一位为下标为-1
- 切片截取一部分操作,字符串、列表、元组都支持切片操作,切片语法:[起始位置:结束位置:步长],注意包头不包尾。
- 字符串操作:已知一个字符串mystr
mystr.find(str,start=0,end=len(mystr)) #检测str是否在mystr中,如果检测到返回下标值,否则返回-1 mystr.index(str,start=0,end=len(str)) # 和find()方法类似,但如果检测不到会报错
mystr.count(str,start=0,end=len(str)) #str在mystr中start到end之间出现的次数
mystr.replace(str1,str2,mystr.count(str1)) #把mystr中的str1替换成str2,如果 count 指定,则替换不超过 count 次.
mystr.split(str=" ",maxsplit=2) #以str为分隔符切片mystr,如果maxsplit有指定值则分割maxsplit个字符串 mystr.splitlines() #按行分割 mystr.capitalize() #字符串中第一个字符大写 mystr.title() #每一个单词首字母大写 mystr.startswith(str) #检查mystr是否已str字符串开头,是返回True,否返回False mystr.endswith(str) #检查mystr是否已str字符串结尾,是返回True,否返回False mystr.lower() # 所有大写字母为小写 mystr.upper() #所有小写字母为大写 mystr.ljust(width) #返回一个原字符串左对齐,并使用空格填充至长度 width 的新字符串 mystr.rjust(width) #返回一个原字符串右对齐,并使用空格填充至长度 width 的新字符串 mystr.center(width) #返回一个原字符串居中,并使用空格填充至长度 width 的新字符串 mystr.lstrip() #删除mystr左边的空白字符 mystr.rstrip() #删除mystr右边的空白字符 mystr.strip() #删除mystr两端的空白字符 "rfind,rindex方法同find()和index()相同,只不过是从右边开始查找,但是下标还是从左边开始数。" mystr.partition(str) #把mystr分割成str前,str,str后三部分。组成元组 mystr.rpartition(str) #把mystr分割成str前,str,str后三部分,从右边开始。组成元组 mystr.isalpha() #判断mystr是否都是字母,是返回true,否返回false mystr.isdigit() #判断mystr是否都是数字,是返回true,否返回false mystr.isalnum() #判断mystr是否都是数字或字母,是返回true,否返回false mystr.isspace() #判断mystr是否只包含空格,是返回true,否返回false mystr.join(iterable) #iterable是一个可迭代对象
列表
-
列表的遍历for while
-
列表的相关操作
# 增加 li1.append(li2) #将li2作为元素添加到li1中 li1.extend(li2) #将li2中的每一个元素逐一添加到列表li1中 li1.insert(index,object) #在li1指定位置index处插入元素object # 修改元素 li1[index] = object # 查询元素 in,not in,index,count in not in #存在或不存在 li1.index(object,start,end) li1.count(object,start,end) # 查询下标或次数在start和end之间,注意包头不包尾 # 删除元素 del 关键字 #根据下标删除 li1.pop()方法 #删除最后一个元素 li1.remove(元素) # 删除指定元素 # 排序 li1.sort() #正序 li1.sort(reverse=True) #倒序
-
列表嵌套应用
# 3个办公室随机分配8个老师的问题 import random offices = [[], [], []] teachers = ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H'] for i in teachers: index = random.randint(0, 2) offices[index].append(i) print(offices)
元组(不可变类型,不能修改元素、删除元素)
- 定义一个元素的元组,tuple1 = (1,)
- 元组操作:
- 通过下标访问元组元素:tuple1[index]
- tuple1.count(object,start,end) 查询object元素在元组中从start到end(左闭右开)的数量。
- tuple1.index(object,start,end) 用法与列表中的用法相同
字典
- 语法格式:{key1:value1,key2:value2,…}
- 字典常见操作dict1
- 修改元素、添加元素:dict1[key] = value 当key不存在即为添加元素,存在即为修改元素
- 查询元素 dict[key]
- 删除 del关键字 clear()方法
- 删除元素 del dict1[key]
- 删除整个字典 del dict1
- 清空字典 dict1.clear()
#####注意:清空字典该字典依然存在只不过是空字典,而删除字典后这个字典不存在。
-
字典常见操作2
- len(dict1) 获取字典中键值对个数
- dict1.keys() 获取字典中所有key的列表
- dict1.values() 获取字典中所有value的列表
- dict1.items() 获取字典中所有(key,value)元组的列表
-
字典的遍历
-
for i in dict1: 默认遍历字典的key
-
for i in dict1.keys(): 遍历字典所有的键
-
for i in dict1.values(): 遍历字典所有的值
-
for i in dict1.items(): 遍历字典中所有的元素(元组形式)
-
for i in enumerate(dict1): 带下标遍历
列表打印下标和元素
for i,j in enumerate(li1):
print(i,j)字典打印下标和key
for i,j in enumerate(dict1):
print(i,j) -
公共方法
- “+” 合并 支持的数据类型:字符串、列表、元组
- “*” 复制 支持的数据类型:字符串、列表、元组
- in not in 支持的数据类型:字符串、列表、元组、字典
-
python内置函数
-
cmp(item1,item2) python3.4.3版本已经没有这个函数,被operator模块代替
-
operator模块的使用
import operator operator.lt(a,b) #a<b 从第一个数字或字母(ASCII码)比大小 operator.gt(a,b) #a>b operator.eq(a,b) #a=b 字母完全一样返回True operator.ne(a,b) #a!=b operator.le(a,b) #a<=b operator.ge(a,b) #a>b #返回值均为bool类型
-
enumerate()方法 同时获取下标和元素
-
range(a,b) 从a到b范围内取值,左闭右开区间
-
max(item) 返回容器中元素最大值
-
min(item) 返回容器中元素最小值
-
len(item) 计算容器中元素个数
-
del 有两种用法 del item 或 del(item) 删除变量
函数
-
函数定义的语法格式
def 函数名(参数): 函数体
-
函数调用 函数名([实参(可选)])
-
函数返回值 return
-
函数的四种类型
- 有参数无返回值
- 有参数有返回值
- 无参数无返回值
- 无参数有返回值
-
return使用注意点
- 多个 return, 只有第一个 return 会执行
- 没有 return, 函数返回值为 None
- 如果return 在不同 if 分支中, 根据条件执行对应分支里的 return
-
函数的文档说明
def func1(): """这是函数的文档说明""" pass help(func1)
函数的高级用法
-
全局变量和局部变量
-
全局变量定义在函数外部,所有的函数都能访问全局变量
-
局部变量定义在函数内部
-
修改全局变量 global
-
-
函数参数
- 位置参数
- 传参时以默认位置传入
- 关键字参数
- 传参时使用key=value的形式传入
- 缺省参数
- 在形参中默认有值的参数,称为缺省参数
- 当调用函数时,如果缺省参数没有传入,则使用默认值
- 当位置参数和缺省参数同时存在时,缺省参数必须位于最后
- 不定长参数
- 不定长位置参数 *args
- 不定长关键字参数 **kwargs
- 当缺省参数、不定长参数同时存在时,可以将缺省参数放到不定长位置参数*args后面,但是**kwargs参数必须放在最后。
- 位置参数
-
###组包和拆包
# 以*args为例 # 组包和拆包 def run(a, *args): # 第一个参数传给了a print(a) # args是一个元组,里面是2和3两个参数 print(args) # *args是将这个元组中的元素依次取出来 print("对args拆包") print(*args) # *args 相当于 a,b = args print("将未拆包的数据传给run1") run1(args) print("将拆包后的数据传给run1") run1(*args) def run1(*args): print("输出元组") print(args) print("对元组进行拆包") print(*args) run(1, 2, 3) # 后面的2和3
- 形参中的*args其实真正接收参数的是args,把传进来的数据传入到args这个元组中
- 函数体里的args依然是那个元组,但是*args的含义就是把元组中的数据进行拆包,也就是把元组中的数据拆成单个数据。
- 对于args这个元组,如果不对其进行解包,就将其作为实参传给其它以*args作为形参的函数时,args这个元组会看看作一个整体,作为一个类型为元组的数据传入。
-
python中交换两个变量的值
- a,b = b,a
引用
- 在python中,值是靠引用传递的
- 使用id()查看内存地址
可变类型和不可变类型
-
数据能够直接修改的就是可变类型,否则就是不可变类型
-
可变类型有 列表、字典、集合
-
不可变类型有 元组、字符串、数字
-
注意:字典的键只能是不可变类型
-
+= 和 = + 通过引用分析不同
# 可变类型 a = [1] b = [2] print(id(a)) print(id(b)) a += [1] b = b + [1] print(id(a)) print(id(b))
输出结果为
/usr/bin/python3.6 /home/zorozhang/PycharmProjects/python复习/demo08.py 140200644596104 140200644599368 140200644596104 140200669502344 Process finished with exit code 0
对于可变类型来说,+=是本地操作,内存地址不会改变。而= +会修改内存地址。
# 不可变类型 a = (1,) b = (2,) print(id(a)) print(id(b)) a += (1,) b = b + (2,) print(id(a)) print(id(b)) a = 1 b = 2 print(id(a)) print(id(b)) a += 222 b = b + 555555 print(id(a)) print(id(b))
执行结果为
/usr/bin/python3.6 /home/zorozhang/PycharmProjects/python复习/demo08.py 140677054243616 140677028201752 140677028205320 140677028206984 10964896 10964928 10972000 140677028340624 Process finished with exit code 0
由此可见,不可变类型无论哪种情况内存地址都会发生改变。
递归函数:本质是在函数内部不断的调用自身的函数,例:阶乘计算
列表推导式的基本格式
list = [i for i in range(1,4)]
文件操作
-
文件打开与关闭
# open函数用法 f = open('文件名','访问模式') f.write('写入内容') content = f.read() #读取数据 content = f.readlines() #按照行的方式把整个文件中的内容进行一次性读取 content = f.readline() #读取一行 # 文件关闭 f.close()
访问模式:
r:只读方式打开文件,指针在文件开头。默认模式
w:只写,如果文件已存在则将其覆盖,如果不存在,创建新文件。
a:追加,如果文件存在,指针将会放在文件的结尾。如果不存在则创建新文件进行写入。
rb:二进制打开只读。
wb:二进制打开只写入。
ab:二进制追加。
r+:读写,文件指针会放在文件开头。以读为主。
w+:读写,以写为主。如果该文件已存在则将其覆盖。如果该文件不存在,创建新文件。
a+:读写,追加为主。
rb+:二进制读写。以读为主。
wb+:二进制读写,以写为主。
ab+:二进制追加。
文件的相关操作 os模块的使用
import os
# 文件重命名
os.rename('原文件名','修改后的文件名')
# 删除文件
os.remove(删除的文件名)
# 创建文件夹
os.mkdir(文件夹名)
# 获取当前目录
os.getcwd()
# 改变默认目录
os.chdir(目标目录)
# 获取目录列表
os.listdir(目标目录)
# 删除文件夹
os.rmdir(文件夹名)
面向对象
-
面向过程:根据业务逻辑从上到下写代码
-
面向对象:将数据和函数绑定到一起进行封装,减少代码的重复性
-
定义类和创建对象、添加和获取对象的属性、通过self获取对象的属性略。
-
魔法方法
__init__()方法 初始化方法,用来做变量初始化和赋值操作,在类实例化对象的时候,会被自动调用,可以传入参数
__str__()方法,用来显示信息,需要return一个数据,且只有self一个参数,当在类的外部print(对象)时打印这个数据。如果没有定义__str__方法,默认打印对象的内存地址
__del__()方法,当对象被删除时自动调用
-
继承
继承的语法格式略
子类重写父类的同名方法和属性问题。默认使用子类
#子类的魔法属性__mro__决定了属性和方法的查找顺序 子类.__mro__
子类在内部调用父类的方法,通过super()调用父类的方法略
当有多层继承时,使用super()可以逐一调用所有的父类方法,但只执行一次。调用顺序遵循mro类属性的顺序
-
私有权限
- 在属性名和方法名前面加双下划线
注意:
- 类私有属性和私有方法不能通过对象直接访问,但可以在本类内部访问
- 类私有属性和方法不能被子类继承,子类也无法访问
- 私有属性和私有方法往往用来处理类的内部事情,不通过对象处理,起到安全作用
- 获取和修改私有属性的值,可以通过访问公有方法来获取和修改私有属性的值。
-
多态的概念:不关心对象的类型,只关心对象是否有指定的属性和方法。定义时的类型和运行时的类型不一样,此时就称为多态。
注意:
-
多态是建立在继承的基础上的,实例化的对象可能来自两个不同的子类,这两个子类继承自一个父类,但是调用相同的方法时返回不同的结果,这就是所谓的多态。
#具体代码实现 class F1(object): def show(self): print('F1.show') class S1(F1): def show(self): print('S1.show') class S2(F1): def show(self): print('S2.show') def Func(obj): """Func函数需要接收一个F1类型或者F1子类的类型""" print(obj.show()) s1_obj = S1() Func(s1_obj) # 在Func函数中传入S1类的对象 s1_obj,执行 S1 的show方法,结果:S1.show s2_obj = S2() Func(s2_obj) # 在Func函数中传入Ss类的对象 ss_obj,执行 Ss 的show方法,结果:S2.show
-
-
类属性和实例属性
-
类属性
# 公有类属性可以在类外访问,可以通过类对象和实例对象访问 # 私有的类属性不能在类外访问
类属性必须通过类对象去修改,
-
实例属性
实例属性通过实例对象去访问。实例对象不能修改类属性。
-
-
类方法
- 通过@classmethod装饰,参数cls,能够通过实例对象和类对象访问。
- 可以通过类方法对类属性进行修改
-
静态方法通过@staticmethod装饰,不需要定义产生,可以通过对象和类来访问
-
__new__
方法和__init__
方法__new__
方法是真正的构造方法。至少有一个参数cls,代表要实例化的类。此参数在实例化时由python解释器自动提供。__new__
必须要有返回值,可以返回父类__new__
出来的实例,或者直接是object的__new__
出来的实例__init__
方法不要返回值
-
单例模式
异常
-
捕获异常
try ...except....as 给异常取别名
else 如果没有捕获异常则执行
finally 不管有没有捕获异常都执行
-
抛出自定义异常
class ShortInputException(Exception): #继承自Exception类 '''自定义的异常类''' def __init__(self, length, atleast): #super().__init__() self.length = length self.atleast = atleast def main(): try: s = input('请输入 --> ') if len(s) < 3: # raise引发一个你定义的异常 raise ShortInputException(len(s), 3) except ShortInputException as result:#x这个变量被绑定到了错误的实例 print('ShortInputException: 输入的长度是 %d,长度至少应是 %d'% (result.length, result.atleast)) else: print('没有异常发生.') main()
自定义异常类继承自Exception类,在使用时先raise抛出自定义异常,然后进行捕获。
模块
-
python解释器对模块的搜索顺序为
当前目录–>shell变量PYTHONPATH下的每个目录(环境变量)–>默认路径(一般为/usr/local/lib/python/)
-
模块搜索路径存储在system模块的sys.path的变量中。变量里包含当前目录,PYTHONPATH和由安装过程决定的默认目录。
-
模块中
__all__
的作用# 在demo01文件中定义模块,没有__all__ class Test(): def test(self): print("Test类中的test函数") def test1(): print("这是test1函数") def test2(): print("这是test2函数")
# 在demo02中导入 from demo11 import * test = Test() test.test() test1() test2() # 执行结果为 /usr/bin/python3.6 /home/zorozhang/PycharmProjects/python复习/demo12.py Test类中的test函数 这是test1函数 这是test2函数 Process finished with exit code 0
如果在demo01中加入
__all__=['Test','test1']
,如下:__all__ = ['Test','test1'] class Test(): def test(self): print("Test类中的test函数") def test1(): print("这是test1函数") def test2(): print("这是test2函数")
则执行demo02时:
/usr/bin/python3.6 /home/zorozhang/PycharmProjects/python复习/demo12.py Test类中的test函数 这是test1函数 Traceback (most recent call last): File "/home/zorozhang/PycharmProjects/python复习/demo12.py", line 7, in <module> test2() NameError: name 'test2' is not defined Process finished with exit code 1
总结:
- 如果一个文件中有
__all__
,那么意味着使用from … import * 导入模块时,不在这个变量中的元素不会被导入。
- 如果一个文件中有
-
模块中
__name__
的作用-
如何解释
__name__
的作用,可以通过以下代码解释# 在test.py中写入以下代码 def test1(a,b): print("in this module __name__ is %s" % __name__) return a+b # if __name__ == '__main__': # 当没有这句代码时 # 以下为测试代码 result = test1(2,4) print(result) # 在main.py中写入以下代码 from demo13 import * result2 = test1(2,3) print(result2)
两个py文件执行结果为:
# 运行test.py文件 /usr/bin/python3.6 /home/zorozhang/PycharmProjects/python复习/demo13.py in this module __name__ is __main__ 6 Process finished with exit code 0
# 运行main.py文件 /usr/bin/python3.6 /home/zorozhang/PycharmProjects/python复习/demo14.py in this module __name__ is demo13 6 in this module __name__ is demo13 5 Process finished with exit code 0
我们的本意应该是测试代码在测试文件中执行,而在别的文件中不需要执行。
为了解决这个问题,python提供了一个变量
__name__
将test.py中的
if __name__ == '__main__':
放开,即可以解决这个问题。因此,模块中
__name__
的作用是可以显示python脚本的名称,如果是在本地执行的,__name__
为__main__
,如果是被引入执行的,__name__
则显示模块名。
-
-
包的概念
- 包是将有联系的模块放在同一个文件夹下,再在文件夹下创建
__init__.py
文件,那么这个文件夹就称之为包。 - 包中
__init__.py
文件的作用:控制着包的导入行为。 - 在
__init__.py
文件中,定义一个__all__
变量,它控制着 from 包名 import *时导入的模块
- 包是将有联系的模块放在同一个文件夹下,再在文件夹下创建
-
包的导入
- import 包名.模块名
- import 包名.模块名 as 别名
- from 包名.模块名 import …
- from 包名 import *
- from 父包名.子包名.模块 import …