Python基础学习
第三章 序列
列表(list)
元组(tuple)
字典(dict)(day04)
字典:
键值对组成、无序可变序列;
通过键对象获取、删除、更新值对象
键对象:任意不可变数据(整数、浮点数、字符串、元祖)且不可重复
值对象:任意数值且可重复
定义方式:
a = {'name':'czn','age':'16','job':'engineer'}
创建方式:
1、
a = {'name':'czn','age':'16','job':'engineer'}
2、
dict(name ='czn',age='16',job='engineer')
or
dict([(元组)(、、、)])
内部无内容为空
3、zip() 列表 => dict(zip())
4、fromkeys 创建值为空的字典 => dict.fromkeys([‘键’])
元素访问:
1、a[’ ‘] 若不存在报错
2、a.get(’ ') 不存在返回指定内容 ***推荐:
列出所有键对: a.items( ) 键: a.keys( ) 值: a.values( )
3、len( ) 键值对个数 ;in 判断’键’是否在字典中
字典元素添加、修改、删除
(单)1、新增键值对 a.[’ ‘]=’ ’ 键重复则覆盖
(多)2、update( ) 新字典全部添加到旧字典上: a.update(b) 重复则覆盖
3、del(a[’ ‘]) 指定删除; a.clear()全删; a.pop(’ ‘) 删除并返回指定值
4、a.popitem( ): 字典无序,随机弹出
序列解包
用于元组、列表、字典(多个变量赋值)
字典:默认/键 = a.keys( ) ;值 = a. values( ); 键值对 = a.items( )
字典核心底层原理:
散列表=稀疏数组(有空白元素的数组)
单元:bucket(包括:键对象引用、值对象引用)
*所有bucket结构大小一致、采用偏移量读取指定
存
hash( ) 得散列值 => bin( )二进制 => 将对应序号写入bucket
查找键
hash( ) (基本同上)
总结:
1、键必须散列
2、内存占据大;空间换时间
3、查阅快
4、添加新建可能导致扩容:不要遍历同时修改
集合(set)
集合:
无序可变序列、元素不重复
集合底层是字典,其元素为字典中的键对象
创建、添加、删除
1、a = { }
2、a.add( )
将列表、元组转换 set(a)
删除 a.remove( ) 指定删除 a.clear( )全部删除
其他相关操作
并集 a|b or a.union(b)
交集 a&b or a.intersection(b)
差集 a-b or a.difference(b)
第四章 控制语句
控制语句可看作”混凝土“,”砖块“便是变量、数据类型、序列等
安装PyCharm
选择结构
判断条件执行分支:单分支、双分支和多分支
单分支结构(注意冒号的补充)
if 条件:(逻辑、关系、算术)
----语句/语句块(多条语句缩进一致)
*操作:int(input(’***********:’))
条件表达式:在False、0、0.0、None、空序列、空range对象、空迭代对象时为False;其余均为True
条件表达式中不能有赋值操作符”=“
双分支结构
if 条件:
----语句/语句块
else:
----语句/语句块
三元体条件运算符(简洁易懂)
条件为真时的值 if(条件表达式) else 条件为假时的值
多分支结构
if 条件:
----语句/语句块
elif条件:
----语句/语句块
…
else:
注意冒号的添加,以及format规格化的使用
(条件补全后可调换排序)
选择结构嵌套(注意排序和缩进量)
注意缩进间的关系
案例:通过算法优化来减少代码量
循环结构
循环执行一条或多条语句:条件符合反复执行
循环体中需存在语句改变条件表达式以避免死循环
While循环
while条件表达式:
----循环体语句(需避免死循环)
for循环(day05)
语法格式:
for 变量 in 可迭代对象(序列等):
----循环体语句
操作:mypy007
range对象
迭代器对象,生成指定范围内的数字序列
range(start, end [,step] )
操作:mypy008(注意range中结束范围的取值,包头不包尾)
嵌套循环结构与选择结构实现代码的简略
嵌套循环
循环之内套循环(多重循环)
经典练习:打印:数据、99乘法表、表格(注意打印分隔语句位置)
break语句
break用于结束整个循环,存在嵌套循环时跳出最近一层的循环
操作:mypy010
continue语句
continue用于结束本次循环,存在嵌套循环时同样跳出最近一层的循环
操作:mypy011(注意先分析要求再编辑)
else语句(python特殊语法)
while、for循环可附带一个else语句。如果循环没有被break语句结束,则循环结束后执行else子句;否则不执行。
while 条件表达式:
----循环体
else:
----语句块
or:
for 变量 in 可迭代对象:
----循环体
else:
----语句块
操作:mypy012
循环代码的优化(性能提升)
原则:
1、尽量减少循坏内部不必要的计算
2、嵌套循环中,尽量减少内层循环的计算(往外提)
3、局部变量查询较快,尽量使用局部变量
操作:mypy013
其他优化手段:
1、连接多个字符串使用join()非+
2、列表进行元素插入和删除尽量在尾部操作
使用zip()并行迭代
用zip函数对多个序列进行并行迭代,zip()函数在最短序列用完时就会停止
操作:mypy014
推导式创建序列(集中性再讲述一次)
将循环和条件判断结合、避免冗长代码,典型python风格
列表推导式
生成列表对象,语法:[表达式 for item in 可迭代对象] or {表达式 for item in 可迭代对象 if条件判断}
可添加多个for循环
字典推导式
生成字典对象,格式:{key_expression : value_expression for 表达式 in 可迭代对象 if 条件判断}
类似于列表,可添加if条件判断和多个for循环
课后练习存在字母重复出现的问题尚未解决
集合推导式
格式:{表达式 for item in 可迭代对象 } or {表达式 for item in 可迭代对象 if条件判断}
生成器推导式(生成元组)
一个生成器只能运行一次
练习(绘制不同颜色同心圆、棋盘)
mypy016、017(注意作业比对老师模板)
第五章 函数用法和底层分析
函数
函数是可重用的程序代码块,实现代码的复用及一致性。
程序由一个个任务组成,函数即代表一个任务或功能。
函数是代码复用的通用机制
python中函数的分类
1、内置函数(str()、list()、len()等)
2、标准库函数(利用import语句导入库)
3、第三方函数库(下载安装后import调用)
4、用户自定义函数
函数定义和调用
定义函数的语法:
def 函数名([参数列表]):
----’’‘文档字符串’’’(解释函数功能)
----函数体/若干语句
要点:
1、def+空格+函数名称,python执行def会创建一个函数对象并绑定到函数名变量上
python里一切都是对象(包括函数)
2、参数列表
圆弧括号内是形式参数列表,多个参数需要逗号隔离
形式参数无需声明类型,无需制定函数返回值类型
无参数也须保留空括号
实参列表必须与形参列表一一对应
3、return返回值
4、调用函数前必须先定义函数
形参和实参
形参:定义函数时使用
实参:调用函数时使用
文档字符串(函数的注释)
调用help(函数名.doc)获取函数对应的注释
返回值
1、若函数包含return语句,则结束函数执行并返回值;
2、多函数体中不包含return语句,则返回None值;
3、要返回多个返回值,使用列表、元组、字典、集合将多个值储存起来即可
底层分析(day06)
操作:mypyfunc_004
变量的作用域(全局变量和局部变量)
全局变量 | 局部变量 |
---|---|
1、在函数和类定义之外声明的变量(作用域为定义的模块,从定义位置开始直到位置结束) | 1、在函数体(包含形式参数)声明的变量 |
2、降低了函数的通用性和可读性 | 2、引用比全局变量快,优先考虑使用 |
3、一般做常量使用 | 3、 若与全局变量同名,在函数内隐藏全局变量、仅使用局部变量 |
4、函数内改变全局变量的值,使用global声明 |
调用函数产生栈帧(stack frame),即存放局部变量,调用结束后消除
局部变量和全局变量的效率测试:
在强调效率以及循环次数多的情况下,将全局变量转为局部变量提高效率
参数的传递
本质是从实参到形参的赋值操作:
1、对“可变对象”进行“写操作”,直接作用于原对象本身(字典、列表、集合、自定义对象等)
2、对“不可变对象”进行“写操作”,产生一个新的“对象空间”,并用新值填充这块空间(数字、字符串、元组、function等)
传递“可变对象”:mypyfunc_007
传递“不可变对象”:mypyfunc_008
浅拷贝和深拷贝
参数传递底层原理:copy(浅拷贝)和 deepcopy(深拷贝)
浅拷贝:不拷贝子对象的内容,只拷贝子对象的引用
深拷贝:连子对象的内存全部拷贝一份,对子对象的拷贝不影响源对象
修改浅拷贝可能对源项有一定程度的修改
深拷贝完全独立,对源项无任何影响
传递不可变对象是浅拷贝
参数的几种类型
位置参数:参数个数不匹配则报错
默认值参数:通过参数名称来匹配
命名参数:默认值参数必须位于其他参数后面
可变参数:1、*param,将多个参数收集到一个元组中;2、**param将多个参数收集到一个字典中;
强制命名参数:带星号的‘可变参数’后面增加新的参数,必须是“强制命名参数”
lambda表达式和匿名函数
lambda表达式用来声明匿名函数,是一种简单的、同一行中定义函数的方法,实际生成了一个函数对象。
lambda表达式只允许包含一个表达式,不能包含复杂语句,该表达式的计算结果就是函数的返回值,
基本语法:
lambda arg1,arg2,arg3… : <表达式>
arg1/arg2/arg3为函数的参数,<表达式>相当于函数体。运算结果是表达式的运算结果。
eval(“”)函数
功能:将字符串str当成有效表达式来求值并返回计算结果
语法:eval( source[,globals[,locals]])->value
参数:source:一个python表达式函数或函数compile()返回的代码对象
globals:可选,必须是dictionary
locals:可选,任意映射对象
递归函数
自己调用自己的函数,在函数体内部直接或间接调用自己
包含:1、终止条件(表示递归何时结束) 2、递归步骤(把第n步的值与n-1步相关联)
先进后出后进先出
操作:mypyfunc_015
嵌套函数(内部函数)(day07)
在函数内部定义的函数,外部无法直接调用内部函数
使用情况:1、封装-数据隐藏
2、贯彻DRY(don’t repeat yourself)原则,避免重复代码
3、闭包(后续讲)
nonlocal关键字(与global类似)
修改外部函数的参数需要调用nonlocal函数
LEGB规则
python在查找“名称”时,按照legb规则查找:
Local–>Enclosed–>Global–>Built in
Local:指函数或者类的方法内部
Enclosed:指的是嵌套函数(一个函数包裹另一个函数,闭包)
Global:指模块中的全局变量
Built in:指Python为自己保留的特殊名称
第六章 面向对象编程
面向对象(Object oriented Programming,OOP)python中一切皆对象,支持面向过程、面向对象、函数式编程等多种编程范式
面向对象和面向过程的区别
面向过程(Procedure Oriented)思维
“程序的逻辑流程” 、“执行者思维”,适合编写小规模程序;如“开车”
面向对象(Object Oriented)思维
“软件中对象之间的关系”、“设计者思维”、适合编写大规模程序;如:“造车”
面对复杂问题,倾向于面对对象思维,从问题中找名词(面对过程思维更偏向于找动词),确定这些名词哪些可以作为类,再根据问题需求确定类的属性和方法,以及类之间的关系。
总结
面向过程和面向对象都是解决问题的思维方式,都是代码组织的方式;解决简单问题可使用面向过程;解决复杂问题,宏观上使用面向对象把握,微观处理上仍然是面向过程。
对象的进化
简单数据:10,20…;数组:[10,20,30]…;结构体struct:将不同类型的数据放在一起(C语言中的数据结构);对象:将不同类型的数据、方法(即函数)放到一起
class Student(首字母大写);给出类属性、定义实例属性、实例方法
类(class)的定义
类用来规范代码,类将方法(行为)和属性(状态)放在一起(对象里的方法和属性由类产生)类如同模具
操作:mypyoo_001
构造函数__init__()
主要用于初始化对象,创造对象由__new__()方法负责,但一般无需定义
一个Python对象包含以下部分:
- 1、id(identity 识别码)
- 2、type(对象类型)
- 3、value(对象的值)
- (1)属性(attribute)
- (2)方法(method)
init()的要点如下:
1、名称固定,必须为:init()
2、第一个参数固定,必须为self
3、构造函数通常用来初始化实力对象的实例属性,例如:mypyoo_001
4、通过”类名(参数列表)“来调用构造器
实例属性
从属于实例对象的属性,也称”实例变量“
1、一般在__init__()方法中通过 self.实例属性名 = 初始值 定义
2、在本类的其他实例方法中,也通过self进行访问:self.实例属性名
3、创建实例对象后,通过实例对象访问:
obj01 = 类名() #创建对象,调用__init__()初始化属性
obj01.实例属性名 = 值 #可以给已有属性赋值,也可以新加属性
实例方法
从属于实例对象的方法。格式: 与函数基本一致,多出self部分
def 方法名(self[,列表形参]):
----函数体
调用:对象.方法名([实参列表])
定义实例方法第一个参数必为self,调用实例方法也不需要给self传参数
其他操作:
1、dir(obj)获得对象的所有属性、方法
2、obj.dict 对象的属性字典
3、pass 空语句
4、isinstance(对象,类型) 判断对象是不是指定类型
类对象
当解释器执行class语句时,会创建一个类对象
类属性和类方法
类属性
从属于”类对象”的属性,也称为“类变量”,可以被所有实例对象共享。定义方式:
class 类名:
----类变量名 = 初始值
在类中或外部,可通过:“类名。类变量名”来读写
类方法
从属于类对象的方法,通过装饰器@classmethod定义,格式如下:
@classmethod
def 类方法名(cls [,形参列表]):
----函数体
要点:
1、@classmethod必须位于方法上面一行
2、第一个cls必须有,cls即“类对象”本身
3、调用类方法:“类名.类方法名(参数列表)”,参数列表不给cls传值
4、类方法中访问实例属性和实例方法会错误
5、子类继承弗雷方法时,传入cls是子类对象,而非父类对象
静态方法
定义与“类对象”无关的方法,需要通过类调用,通过装饰器@staticmethod定义,格式如下:
@staticmethod
def 静态方法名([形参列表]):
----函数体
要点:
1、@staticmethod必须位于方法上面一行
2、调用静态方法:“类名.静态方法名(参数列表)”
3、静态方法中访问实例属性和实例方法会错误
__del__方法(析构函数)和垃圾回收机制
__del__方法(析构函数)用于实现对象被销毁时所需要的操作
Python实现自动的垃圾回收:对象没被引用时由垃圾回收器调用__del__方法;
也可用del语句删除对象(系统自动提供__del__方法一般无需自定义析构函数)
__call__方法和可调用对象
定义了__call__方法的对象,称为”可调用对象“,即该对象可以像函数一样被调用
方法没有重载(day08)
不要使用重名法,Python中方法没有重载
定义多个重名法只有最后一个方法有效。
方法的动态性
修改外部调用,用路径指定调用,改变方法实现动态变化
私有属性和私有方法(实现封装)
要点:
1、两个下划线开头的属性是私有的(private),其他是公共的(public)
2、类内部可以访问私有属性(方法)
3、类外部不能直接访问私有属性(方法),“通过_类名__私有属性(方法)名”访问
操作:mypyoo_009
@property装饰器
将方法的调用方式变成“属性调用”;增加属性的get、set方法
面向对象的三大特征
封装(隐藏):隐藏对象的属性和实现细节,只对外提供必要的方法
继承:继承可以让子类具备父类的特性,提高代码的重用率
多态:同一个方法调用由于对象不同会产生不同的行为
继承
“代码复用”的重要手段。已有的类:“父类或基类”;新的类:“子类或派生类”。 与显示世界对应
语法格式:一个子类可以继承多个父类:
class 子类类名(父类1[,父类2…]):
----类体
(若未指定父类,则默认父类为object类;object是所有类的父类,定义一些所有类共有的默认实现,如__new__()。)
定义子类时必须在其构造函数调用父类的构造函数:父类名.init(self,参数列表)
类成员的继承和重写
成员继承:子类继承父类除构造方法之外的所有成员
方法重写:子类可以重新定义父类中的方法,会覆盖父类的方法,也称为“重写”
查看类的继承层次结构
类的方法 mro()
类的属性 mro
object根类(所有类的父类)
dir()查看对象属性
内置函数dir(),可以查看指定对象的所有属性
操作:mypyoo_014
重写__str__()方法
操作:mypyoo_015
多重继承
支持多重继承,可具备多个父类的特点,但类的整体层次非常复杂,尽量避免使用
MRO()函数
MRO()(Method Resolution Order)方法解析顺序,(多个)父类中有相同的名字,在子类没指定父类时,解释器将按“从左向右”的顺序搜索。
操作:mypyoo_016
super()获得父类的定义(非对象)
操作:mypyoo_017
多态
同一个方法调用由于对象不同会产生不同的行为
要点:
1、多态是方法的多态,没有属性的多态
2、多态存在的2个必要条件:继承、方法重写
操作:mypyoo_018
特殊方法和运算符重载
Python运算符实际上是通过调用对象的特殊方法实现
操作:mypyoo_019
特殊属性
双下划线开始和结束的属性,有特殊用法
操作:mypyoo_020
对象的浅拷贝和深拷贝
变量赋值操作:形成两个变量,实际仍指向同一个对象
浅拷贝:对象包含的子对象内容不拷贝,源对象和拷贝对象会引用同一个子对象
深拷贝:deepcopy函数,递归拷贝对象中包含的子对象。源对象和拷贝对象所有的子对象也不同
操作:mypyoo_021
组合
is-a 继承
has a 组合
操作:mypyoo_022、mypyoo_021_01
设计模式(23种)——工厂模式实现和单例模式
工厂模式
实现了创建者和调用者的分离,使用专门的工厂类将选择实现类、创建对象进行统一的管理和控制。
操作:mypyoo_023
单例模式
确保一个类只有一个实例,并且提供一个访问该实例的全局访问点
操作:mypyoo_024
操作:mypyoo_025 工厂模式与单例模式的整合
第七章 异常(day09)
导引问题:try:------except:
异常机制本质:指程序运行过程中出现的非正常现象;异常处理:指程序出现问题时依然可以正确地执行剩余的程序
异常的类:BaseException(所有异常的父类)–>Exception–>NameError、ValueError、AttributeError等
解决异常的态度:
不慌张,细看信息,定位错误
百度,查看相关资料
赵老师和同学协助解决
try…一个except结构
try:
----被监控的可能引发异常的语句块
except BaseException [as e]:
----异常处理语句块
try…多个except结构
try:
----被监控的可能引发异常的语句块
except Exception1:
----:处理Exception1 的语句块
except Exception2:
----:处理Exception2 的语句块
…
except BaseException [as e]:
----处理可能遗漏的异常语句块
try…except…else结构
有异常执行except语句块,无异常执行else语句块
try…except…finally结构
无论是否发生异常都会执行finally模块
renturn语句一般不放在try、else、finally中,放在整个结构后
常见异常汇总和说明
1、SyntaxError:语法错误
2、NameValue:尝试访问一个没有申明的变量
3、ZeroDivisionReeor:除数为零错误
4、ValueError:数值错误
5、TypeError:类型错误
6、AttributeError:访问对象的不存在熟悉
7、IndexError:索引越界异常
8、KeyError:字典关键字不存在
常见异常汇总表
with 上下文管理
方便实现释放资源的操作,实现自动管理资源,with代码块执行完毕后自动还原进入改代码之前的现场或上下文
语法结构:
with context_expr [as ver]:
----语句块
traceback模块
使用traceback模块查看、打印异常信息
操作:mypro_exception/mypy009
自定义异常类
一般都是运行时异常,通常继承Exception或其子类即可,命名一般以Error、Exception为后缀
自定义异常由rise语句主动抛出
操作:mypy010
Pycharm开发环境的调试
进行调试的核心是断点
行号后面单击即可增加或取消断点
进入调试视图
第八章 文件操作(IO技术)(day10)
从外部存储介质读取数据,将程序产生的数据储存到文件中
文本文件和二进制文件
文本文件:储存普通字符文本,unicode字符集(两个字节表示一个字符,2**16=65536)
二进制文件:数据以字节存储,必须使用专用的软件解码:MP3,MP4,JPG等等
文件操作相关模块表(python中相应的模块)
创建文件对象open()
语法:open(文件名[,打开方式])
文件名可录入全路径D:\a\b.txt,为减少“\”的输入,可以使用原始的字符串:r “d:\b.txt "
f = open(r"d:\b.txt”,“a”)
r:读模式
w:写文件(不存在则创建,存在则重写)
a:追加append(不存在则创建,存在则末尾追加内容)
b:二进制binary(与其他模式组合使用)使用默认操作二进制文件,不添加则处理文本文件
+:读、写模式(与其他模式组合使用)
文本文件的写入
基本操作:1、创建文件对象 2、写入数据 3、关闭文件对象
编码知识
乱码形成的原因是编码和解码不一致
ASCII–>ISO8859-1–>GB2312–>GBK–>GB18030
ASCII—>ISO8859-1—>UTF-8====>/Unicode
write()/writelines()写入数据
writelines:把字符串列表写入文件中,不添加换行符
close()关闭文件流
结合finally或with关键字实现
操作:myfile_002
with语句(上下文管理器)
可以自动管理上下文资源,确保我呢见正确关闭
文本文件的读取
1、read([size]) 从文件读取size个字符,无则读取整个文件
2、readline() 读取一行内容作为结果返回
3、readlines() 每行作为一个字符串存入列表,返回该列表
enumerate(枚举)
操作:myfile_005
二进制文件的读取和写入
f = open(r"d:\a.txt",“wb”) 可写的,重写模式的二进制文件对象
f = open(r"d:\a.txt",“ab”) 可写的,追加模式的二进制文件对象
f = open(r"d:\a.txt",“rb”) 可读的二进制文件对象
操作:myfile_006
文件对象的常用方法和属性
表
使用pickle序列化
将对象转化成“串行化”数据格式,存储搭配硬盘或通过网络传到其他地方
反序列化:将读取的串行化数据转化成对象
格式:
pickle.dump(obj,file) obj要被序列化的对象,file指存储的文件
pickle.load(file) 从file读取数据,反序列化的对象
CSV文件的操作
简单的字符串
操作:myfile_010
os和os.path模块(day11)
直接对操作系统进行操作(windows)
os.system()
操作:os-mypy001
os模块-文件和目录操作
表
os-mypy002
os.path模块
提供了目录相关(路径判断、路径切分、路径连接、文件夹遍历)的操作
表判断、返回、遍历、切分
mypy003、mypy004
walk()递归遍历所有文件和目录
os.walk()方法:
返回一个3个元素的元组,(dirpath,dirname,filenames),
操作:mypy005
shutil模块(拷贝和压缩)
做文件和文件夹的拷贝、移动、删除等;以及文件夹的压缩、解压缩操作
递归算法
自己调用自己从而使问题逐渐简单化
递归结构:定义递归头;递归体
操作:myfile_digui
第九章 模块(module)
模块化程序设计理念
量变引起质变
语句=>函数(属性)=>类=>模块=>包=>程序
模块化语句方便使用和调用:1、任务分解为多个模块 2、实现代码复用 3、可维护性增强
模块化编程的流程
1、设计API,进行功能描述
2、编码实现API中的描述
3、在模块中编写测试代码,并消除全局代码
4、使用私有函数实现不被外部客户端调用的模块函数
模块的导入
import语句导入模块
import 模块名
import 模块1,模块2…
import 模块名 as 模块别名
模块类别:1、使用python编写的代码 2、已被编译的共享库或DLL的C或C++扩展 3、包好一组模块的包 4、使用C编写并链接到python解释器的内置模块
from…import…导入模块下的一个函数/一个类
import()动态导入
传递不同的参数值即导入不同的模块
推荐使用importlib模块
包package的使用
包相当于文件夹,必须有__init__.py的文件
包可以包含模块和子包
导入包操作
本质上仍是导入模块,与导入模块操作一致(模块前加包名)
导入包本质是“导入了包的__init__.py”文件
(不做修改保持功能简单)
import * 希望导入所有子模块,不建议写
包内引用
from … import Module_A #…表示上级目录
from . import Module_A #.表示同级目录
sys.path和模块搜索路径
寻找路径:
1、内置模块
2、当前目录
3、程序的主目录
4、pythonpath目录
5、标准链接库目录
6、第三方库目录
7、.pth文件内容
8、sys.path.append()临时添加的目录
操作:mypro_moudle/b/test_path
模块发布和安装
本地发布
内容复制、setup、发布
本地安装
python目录/Lib/site-packages目录
远程上传到PyPI
注册=>创建用户信息=>上传并远程发布=>官网管理
下载
pip install package-name,通过-update更新