前言 视频
我发现最近需要使用到python的时候越发变得频繁,由于初学的时间至今的确实有点长了,于是想着是时候在复习一下以前的知识点了。正所谓“温故而知新,可以为师”,确实再次看到教材的时候,才发现很多的知识点都已经忘记了。
为了方便后面需要再次复习的时候能够节约自己的学习时间成本,所以写的比较简略,当然也有一些自己常用的东西在里面。
第0章 环境 正所谓磨刀不误砍柴功,Windows安装python的环境太简单,此处忽略。
1.Linux环境 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 # 下载所需要的依赖软件 yum install wget zlib-devel bzip2-devel openssl-devel ncurses-devel sqlite-devel readline-devel tk-devel gcc make zlib zlib-devel libffi-devel -y # 下载python wget https://www.python.org/ftp/python/3.10.13/Python-3.10.13.tgz # 解压安装包 tar -xvf Python-3.10.13.tgz # 源码构建 cd Python-3.10.13 ./configure --prefix=/usr/local/python3.10.13 # 指定安装路径 # 编译和安装 make && make install # /usr/local/python3.10.13为编译好的路径 # /usr/local/python3.10.13/bin路径下的python3.10即为解释器 # 构建软链接 rm -f /usr/bin/python ln -s /usr/local/python3.10.13/bin/python3.10 /usr/bin/python # 修改yum的依赖 vim /usr/libexec/urlgrabber-ext-down 首行改为:#! /usr/bin/python2 vim /usr/bin/yum 首行改为:#! /usr/bin/python2 # 进入python python # 退出 exit()
2.pycharm使用 快捷键 1 2 3 4 5 ctrl + alt + s : 打开软件设置 ctrl + d : 复制当前行代码 shift + alt + 上/下 : 当前行代码上下移动 ctrl + shift + f10 : 运行代码 ctrl + d : 文件重命名
第一章 变量及简单的数据类型 0.常用的函数(遇到新的时候更新)
1 2 3 4 5 语法: map (func,li)func:指一个函数 li:指一个数据序列
1.print()函数 1 2 3 print ("hello world" )print ("python" ,end="," )
2.标识符
命名规则
数字,字母,下划线组成(不能数字开头)
不能使用关键字和函数名
命名规范
变量名,方法名,模块名小写,多个单词_分割。my_name
常量大写。MY_AGE
类名大驼峰。MyName
3.type()返回数据类型 1 2 iCount = 10 print (type (iCount))
4.数据类型 字面量:在代码中,被写下来的的固定的值,称之为字面量
类型
描述
数字(Number)
支持整数(int)浮点数(float)复数(complex)布尔(bool)
整数(int),浮点数(float),复数(complex),如:4+3j,以j结尾表示复数,布尔(bool)
字符串(String)
描述文本的一种数据类型
字符串(string)由任意数量的字符组成
列表(List)
有序的可变序列
可有序记录一堆数据
元组(Tuple)
有序的不可变序列
可有序记录一堆不可变的数据集合
集合(Set)
无序不重复集合
可无序记录一堆不重复的数据集合
字典(Dictionary)
无序Key-Value集合
可无序记录一堆Key-Value型的Python数据集合
5.转义字符 1 2 3 4 5 6 7 8 \t 制表符(Tab) \n 换行符 \' 转义成' \" 转义成" \\ 转义成\ \r 回到当前行的行首 \ 可以做续行符使用
6.大小写转换 1 2 3 4 5 6 7 8 9 皆返回新字符串对象 title() 首字母大写,其余小写 upper() 全部大写 lower() 全部小写 sStr = "hello world" sStr.title()
7.去除空格 1 2 3 4 5 皆返回新字符串对象 strip() 去除全部空格 rstrip() 去除右边空格 lstrip() 去除左边空格
第二章 语法初步 1.缩进与pass python遵循严格的缩进规则,指示代码之间的层级和包含关系。
pass:占位语句,不执行任何实际操作,保留代码形式上的完整性
2.操作符/运算符 1 2 3 4 5 6 7 1. 复合运算符: +=,-=,*=,/=2. 整除与求模: //,%3. 比较运算符: >=,==,!=4. 逻辑运算符: and ,or ,not 5. 求幂: **优先级:算术 > 关系 > 逻辑 > 赋值
3.函数及函数的定义
函数使用
1 2 3 pow (2 ,8 ) abs (-10 ) round (2.5 )
函数的定义
1 2 3 4 5 6 7 8 def <函数名>(<形参>): <函数体> return <返回值列表> eg: def func (a,b,c ): sum_abc = a + b + c return sum_abc
4.占位符 1 2 3 4 5 %d,%f,%s,%x(将以十六进制表示) iNum1 = 10 fNum2 = 10.1 print ("%10d,%10.2f" %(iNum1,fNum2))
5.进制 1 2 3 4 5 6 a = 0xff b = 0b10111 bin (a) oct (a) hex (a)
注意:转换成的是字符串
6.注释 1 2 3 4 1. 2. '''hello world''' 3. """hello world"""
7.获取用户输入 1 iNum_in = int (input ("请输入一个正整数:" ))
8.time模块 1 2 3 4 5 6 import timea = time.time() import datetimeb = datetime.datetime.now() print (b.year,b.month,b.day)
9.math模块 1 2 3 4 5 6 import mathfrom math import sqrtprint (math.floor(6.7 )) print (math.ceil(6.1 )) print (sqrt(9 ))
10.turtle模块 1 2 3 4 5 6 7 8 9 10 11 12 13 import turtlet = turtle.pen() turtle.forward(200 ) turtle.backward(100 ) turtle.circle(50 ) turtle.left(90 ) turtle.right(180 ) turtle.Screen().exitonclick() import turtlet = turtle.Turtle() t.circle(50 ,180 )
第三章 列表(list [])
列表的定义:列表是容纳一系列元素的容器。
列表的索引:0n-1;-1-n .
1.list的操作 1 2 3 4 5 6 7 8 一、元素的增加 a.append("hello" ) a.insert(2 ,"male" ) 二、元素的删除 del a[2 ]a.pop(2 ) a.remove(47 )
2.名字绑定
3.list排序 1 2 3 4 5 6 7 8 a = [2 ,1 ,3 ,5 ,4 ] a.sort() a.sort(reverse=True ) a.sort(key=len ) b = sorted (a) a.reverse()
4.range()函数 1 2 3 4 5 生成[,)区间的整数 range (x)range (x,y)range (x,y,z)
5.list统计 1 2 3 4 a = [1 ,2 ,3 ] max (a)min (a)sum (a)
6.list快速生成 1 2 3 4 5 6 7 8 9 10 11 1. a = [x**3 +100 for x in range (1 ,11 )] 2. a = [[0 ]*8 ]*10 3. a = [[r*c for c in range (8 )] for r in range (10 )] 4. a = [x*x for x in range (10 ) if x % 3 == 0 ]
7.list运算 1 2 3 4 + 两个列表拼接 * 重复n次 in 和 not in
8.list成员函数 1 2 3 4 5 6 7 a.count("b" ) a.clear() a.extend([1 ,2 ,3 ]) a.index(47 ) a.remove(47 ) a.copy() id ()
9.list切片 1 2 3 4 5 a = [x for x in range (10 )] a[1 :10 ] a[:10 ] a[0 :] a[0 ::2 ]
第四章 数据类型及名字绑定 1.元组(tuple ())——只读的列表 1 2 3 用法与用途与列表完全相同 被创建后,其值可以获取但不能修改。所以不能使用remove(),sort()等 (4 ,)
2.集合(set {}) 集合必须满足以下3点:
不重复
无序
元素为可哈希类型(一般是只读的)
不可以使用下标索引
set创建 1 2 3 4 5 6 7 1. a = {1 ,2 ,3 } a = set ([1 ,2 ,3 ]) a = set ("hello" ) 2. a = set ([])
set的基本操作 1 2 3 4 5 6 a = {1 ,2 ,3 } a.add(20 ) a.remove(1 ) a.pop() len (),min (),max (),sum ()in ,not in
set运算 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 s1 = {1 ,2 ,3 } s2 = {1 ,2 } 1. 子集与超集s2任意元素是s1元素,则s2是s1子集。s1是s2超集。 s2.issubset(s1) s1.issuperset(s2) 2. 交集(&),并集(|),差集(-),补集(^)s1 & s2 s1.intersection(s2) s1 | s2 s1.union(s2) s1 - s2 s1.difference(s2) s1 ^ s2 s1.symmetric_difference(s2)
3.字节串(bytes) 背景:与硬件或其他计算机通信时,需要将其他数据类型转换成明确的二进制形式。
bytes是只读的“字节串”类型。
1 2 3 4 5 6 7 8 buffer = b"abcde" print (buffer,type (buffer),len (buffer))buffer = b"\x11\xff\x77" print ('%x' %(buffer[1 ]))buffer = bytes (i+0x10 for i in range (11 )) print (buffer)
1 2 3 4 5 6 7 8 9 10 x = 65534 bufferLittle = x.to_bytes(2 ,"little" ) print (bufferLittle)bufferLittle = x.to_bytes(2 ,"big" ) print (bufferLittle)y = int .from_bytes(b"\xfe\xff" ,"little" ) print (y)
4.字节数组(bytearray) 与bytes功能类似,可修改。
1 2 3 4 5 6 buffer = bytearray (0x00 for x in range (10 )) print (buffer)buffer = bytearray (b"abc" ) buffer[1 ] = ord ("B" ) print (buffer)
5.位运算 按位与(&)、或(|)、位移(>>,<<)、取反(~)、异或(^)
6.名字绑定 “垃圾回收” 机制解释器内部有专门的引用计数来指示当前对象有多少个名字绑定。当对象引用为0后,python解释器会在恰当的时候从内存中销毁这个对象。
注意:python解释器考虑到执行速度的优化,倾向于将名字尽可能绑定在系统已有的对象上,而不是创建对象。
is和== is(id是否相同)
==(对象的值是否相同)
只读/可修改数据类型
只读数据类型 (可忽略名字绑定)
int,float,str,bool,bytes,tuple
可修改数据类型 (有名字绑定)
list,bytearray,set
解决:使用copy() 浅拷贝和deepcopy() 深拷贝(deepcopy()需要导入copy模块)
1 2 3 4 5 6 7 8 9 10 11 import copy a = [1,2,[3,4],5] b = a.copy() c = copy.deepcopy(a) print(id(a),id(b),id(c)) a[2][0] = 2 print(a) print(b) print(c)
7.其他
集合不是序列类型
ord()返回参数字符的Unicode编码
chr()将Unicode编码转换成字符
第五章 条件,循环和其他 1.序列解包 1 2 3 4 5 6 7 8 9 a,b,c = 1 ,2 ,3 a,b = b,c num = 1 ,2 ,3 a,b,c = num a,b,c = "789" a,*b = "123456" *a,b = 1 ,2 ,3 ,4 ,5 ,6 print (a,b)
2.链式赋值
3.条件
非零即真,非空即真
if
if-else
if-elif-else
startswith()和endswith()是str的成员函数,可以判断是否是以参数字符串开头/结尾。
1 2 3 a = "123" print (a.startswith("12" ))print (a.endswith("23" ))
条件语句
1 2 3 num_1 = 1 num_2 = 2 if num_1==1 else 3 print (num_2)
bool运算的短路
4.Python之禅与断言 断言(assert) 可以通过断言进行检查函数内部,若assert后的逻辑判断不成立,程序报错并停止执行。
1 2 3 4 5 6 7 8 score = [21 ,22 ,23 ,24 ,25 ,101 ] def compAverageScore (score ): assert len (score) > 0 assert max (score) <= 100 assert min (score) >= 0 return sum (score) / len (score) print (compAverageScore(score))
Python之禅
5.循环
for循环
while循环
break跳出当层循环
continue结束当次迭代
循环else子句:仅当循环体内部的break未被调用时,else子句才会被执行
1 2 3 4 5 6 7 8 9 10 11 a = [1 ,2 ,3 ] for i in a: print (i) while len (a) > 3 : print (True ) for i in range (len (a)): print (a[i]) else : print ("hello" )
6.序列缝包与循环解包
1 2 3 4 number = [1 ,2 ,3 ,4 ] name = ["王" ,"张" ,"李" ,"孙" ] zip_number_name = zip (number,name) print (list (zip_number_name))
enumerate():将序列元素与元素的下标缝合成一个元组
1 2 3 name = ["王" ,"张" ,"李" ,"孙" ] for idx,name in enumerate (name): print (idx,name)
reversed():接收一个序列,返回一个可迭代对象与原序列相反
1 2 3 name = ["王" ,"张" ,"李" ,"孙" ] for i in reversed (name): print (i)
1 2 3 4 5 scopeTemp = {} scopeTemp["x" ] = 30 scopeTemp["y" ] = 20 exec ("sum = x + y" ,scopeTemp)print (scopeTemp["sum" ])
1 2 a = eval ("1 + 2 + 3" ) print (a)
第六章 字典(dict) 键值对(key value pair)。
字典:能够高效地自动完成键到值的映射。字典同集合一样,不可以使用下标索引
1.创建
字典以一对大括号包裹,键值对以“,”分隔,键值用“:”分隔。
添加新的键值对:字典名[键] = 值
获取给定键的值:字典名[键]
字典中的键值对没有先后顺序(字典不属于序列类型)
在键值对中:
值 可以是任意数据类型
键 必须是可哈希数据类型(通常可哈希数据类型都是只读类型)
list,dict,set不是可哈希数据类型
int,float,str,tuple等是可哈希数据类型
2.dict()函数 1 2 3 4 5 6 items = [("id" ,123 ),("name" ,"王" ),("age" ,26 )] dorothy = dict (items) print (dorothy)dor = dict (name="张" ,age=26 ) print (dor)
3.基本操作 1 2 3 4 5 len ()dro["key" ] dro["key" ] = value del dro["key" ] "age" in dro
注: 字典可嵌套
1 2 3 4 5 6 7 8 9 10 a = { "key" :{ "ren" :{ "001" :{ "name" :"王" } } } } print (a["key" ]["ren" ]["001" ]["name" ])
4.成员函数 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 dor_1 = {'id' : 123 , 'name' : '王' , 'age' : 26 } dor_2 = {'id' : 123 , 'name' : '王' , 'age' : 26 } dor_1.clear() dorCopy = dor_1.copy() d1 = dict .fromkeys(["id" ,"name" ,"age" ],"NoValue" ) d2 = {}.fromkeys(["id" ,"name" ,"age" ],"NoValue" ) """ 两者运行结果: {'id': 'NoValue', 'name': 'NoValue', 'age': 'NoValue'} {'id': 'NoValue', 'name': 'NoValue', 'age': 'NoValue'} """ dor_1= {'id' : 123 , 'name' : '王' , 'age' : 26 } value = d1.get("id" ,"Nokey" ) num = d1.pop("id" ) d1.popitem() dor_1.update(dor_2)
1 2 3 4 5 6 7 8 9 dor_1 = {'id' : 123 , 'name' : '王' , 'age' : 26 } for k in dor_1.keys(): print (k) for v in dor_1.values(): print (v) for k,v in dor_1.items(): print (k,v)
5.小练习 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 """ 问题描述:统计给出的任意字符串序列出现的次数 asdfasdf 输出格式: a:2 s:2 d:2 f:2 """ sList = "asdfasdf" dictList = {} for i in sList: dictList[i] = dictList.get(i,0 ) + 1 for k,v in dictList.items(): print (str (k) + ":" + str (v))
6.容器的通用功能
通用for循环
遍历容器(字典是遍历key)
max
容器内最大元素
min()
容器内最小元素
len()
容器元素个数
list()
转换为列表
tuple()
转换为元组
str()
转换为字符串
set()
转换为集合
sorted(序列, [reverse=True])
排序,reverse=True表示降序得到一个排好序的列表
第七章 函数与抽象 函数:是组织好的,可重复使用的,用来实现特定功能的代码段。
1.函数的定义
函数调用 :调用并执行函数
可执行性 :callable()函数用于鉴别是否是函数
1 2 3 4 5 def a (x=1 ): "这是一个函数" print ("hello" ) a() help (a)
2.函数的参数
默认值参数 :参位于参数列表尾部
非只读类型参数 :会修改函数外部值
关键字参数 :位置传参与关键字传参
1 2 3 def fun (a=1 ,b=2 ): print (a+b) fun(b=4 ,a=1 )
任意数量的参数
这些实参被组织成一个元组
一个函数中,带*号的参数只有一个,且只能放最后(自动合并为一个元组)
1 2 3 4 5 6 一个“*”号的参数不会接收关键字参数,两个“*”可以,且只接受关键字参数 def myPrint (title,*contents ): print (title) for x in contents: print ("\t" ,x) myPrint("Read-only data types" ,"int" ,"float" ,"str" )
1 2 3 4 5 6 7 def myPrint (title,*contents ): print (title) for x in contents: print ("\t" ,x) a = ["Read-only data types" ,"int" ,"float" ,"str" ] myPrint(*a)
1 2 3 4 5 6 def compute (x,y ): return x+y def fun_to_compute (fun_com ): result = fun_com(1 ,2 ) print (result) fun_to_compute(compute)
1 2 fun = lambda x,y:x+y print (fun(1 ,2 ))
3.作用域
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 ''' 将函数内定义的变量声明为全局变量:global y ''' def func (): x = 1 global y z[0 ] = 1000 print (x) print (y) print (z) if __name__ == '__main__' : x = 2 y = 3 z = [1 , 2 , 3 ] func() print (x) print (y) print (z) """ 运行结果: 1 3 [1000, 2, 3] 2 3 [1000, 2, 3] """
1 2 3 4 5 6 7 8 9 def func (): x = 1 print ("local x:" ,x) print ("global x:" ,globals ()["x" ]) if __name__ == '__main__' : x = 2 func()
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 s=0 num = 3 def han (n,a,b,c ): if n>0 : han(n-1 ,a,c,b) global s s+=1 print (a + "->" + c,s) han(n-1 ,b,a,c) han (num,"A" ,"B" ,"c" )
4.小练习 写一个进度条
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 "\r 是回到当前行的行首" progressBefore = 0 def printProgressBar (percent,prefix="" ): global progressBefore if percent-progressBefore < 0.001 : return progressBefore = percent percentStr = ("{0:.1f}" ).format (percent * 30 ) filledLength = int (30 * percent) bar = "*" * filledLength + " " * (30 - filledLength) print ("\r%s |%s|%s%% " %(prefix,bar,percentStr),end="" ) if __name__ == '__main__' : import time for i in range (100 ): printProgressBar((i+1 )/1000 ,prefix="Progress:" ) time.sleep(0.01 )
第八章 面向对象
1.面向对象程序设计(Object Oriented Programming)
类(class) :和数据类型(data type)是同义词。如:“人”这一个类
对象(object) :在OO中,变量(variable),对象,实例(instance)三个术语概念大致相同。如:一个具体的人,小明
属性(attribute) :也称数据成员(data member)。如:姓名,性别等
方法(method) :也称成员函数。如:说话,吃饭
消息(message) :执行一个对象的方法,也称向这个对象发送了一个消息。
对象 = 属性 + 方法
2.创建类 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 from enum import Enumclass Gender (Enum ): male = 0 female = 1 class Person : "user defined class: Person." def __init__ (self,idNo="N/A" ,name="N/A" ): self.sName = name self.gender = Gender.male self.sId = idNo self.iWeight = 0 def speak (self ): print ("Person::speak():" ) print ("I am" , self.sName + "," , "Nice to meet you here." ) def eat (self, weight ): self.iWeight += weight print ("I just eat" , weight, "gram's food." ) def description (self ): assert self.gender in (Gender.female,Gender.male) s = "ID:%s\tName:%s\n" %(self.sId,self.sName) t = "Gender:%s\tBody Weight:%d" %("Male" if self.gender == Gender.male else "Female" ,self.iWeight) return s+t
self参数:基本上是必须的(P125)
定义类的成员函数:第一个参数是self
在成员函数内部:应用对象的形式为self.属性名
构造函数也是成员函数,由解释器自动调用。
3.枚举类型 1 2 3 4 from enum import Enumclass Gender (Enum ): male = 0 female = 1
继承Enum类型,可以用Gender.male来表示男性
4.创建对象 1 2 3 4 5 dora = Person("001" ,"Dora chen" ) dora.gender = Gender.female dora.iWeight = 100 dora.eat(320 ) print (dora.description())
注: 同一类型的多个对象,其属性是相互独立的,但方法却是共享的。
5.封装、接口与实现
复用(reuse) :利用他人代码的方式(from math import *)
接口(interface) :告诉我们功能和使用方法
实现(implementation) :不需要了解的部分(如功能具体的实现算法等)
封装(encapsuation) :实现一个复杂系统并将其细节隐藏起来,只向使用者提供一个简洁易用的接口的工作模式。
组合(composition) :将某些自定义类型的对象作为对象属性/构成部分的方法,也是一种代码复用的手段。
6.继承 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 from Person import Person, Gender class Employee (Person ): def __init__ (self,emplNo,idNo,name ): super (Employee,self).__init__(idNo,name) self.sEmployeeNo = emplNo self.sJobTitle = "" self.sDepartment = "" self.iWeekSalary = 0 def work (self ): print ("I am a" , self.sJobTitle + ", I am working with my partners in department:" ,self.sDepartment) def speak (self ): print ("Employee::speak():" ) super ().speak() print ("I am happy to work for you." ) def description (self ): assert self.gender in (Gender.female,Gender.male) return "调用decription方法"
函数重载(override) :子类重新实现父类的同名函数的方式。调用父类可以使用(super().speak() #等价于Person.speak(self))
术语
同义术语
父类(parent class)
超类(super class),基类(base class)
子类(sub class)
扩展类(derived class),继承类(inherited class)
7.多态、抽象类
8.继承链 1 2 3 4 5 6 issubclass (D,A) D.__base__ isinstance (d,B) d.__class__
9.实现的隐藏
10.万物皆对象
OO的五大特性
万物皆对象
对象皆有类型
程序就是由一堆对象构成,对象间通过发送消息协同工作
每个对象均有自己的存储空间,并由其他对象来构成
相同类型的对象可以接收相同类型的消息
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 def foo (x ): "Function Foo." return x*x print (type (foo),foo)print (foo.__doc__)print ("foo.dir():" ,foo.__dir__()) func = foo print (func(2 ))class Dummy : "Class Dummy." def say (self ): print ("Dummy." ) print (type (Dummy), Dummy)print (Dummy.__doc__)Dummy2 = Dummy d = Dummy2() d.say()
11.类的对象属性和方法 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 class Tomato : objectCount = 0 def __init__ (self ): self.objectCount += 1 Tomato.objectCount += 1 t1 = Tomato() t2 = Tomato() print (Tomato.objectCount)print (t1.objectCount)""" 运行结果: 2 1 """
12.多重继承 不建议使用,会出现“并发症”。推荐看前言中的视频
13.特殊/魔法方法
特殊方法(special method) :函数名前后各两个下划线,长具备特殊用途。
析构函数(destructer) :
14.property属性 property是一种特殊的属性,工作起来像属性,实际上是方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 class Rect : def __init__ (self ): self.width = 0 self.height = 0 self.area = self.width*self.height def setSize (self,size ): self.width, self.height = size self.area = self.width * self.height print ("setSize(): I worked like a common property, but actually, I am a method." ) def getSize (self ): print ("getSize(): I am a method too." ) return self.width,self.height size = property (getSize,setSize) r0 = Rect() r0.size = 120 ,20 r1 = Rect() r1.size = 13 ,30 print ("Rect:" , r0.size, "Area =" ,r0.area)print ("Rect:" , r1.size, "Area =" ,r1.area)''' 1.通过property()"函数"我们创造了一个size属性,并指定了这个属性的读取函数和设置函数 2.对size属性的赋值会执行setSize()方法,对size取值则会执行getSize()方法 3.size属性是虚拟的,它本身并不存储任何值。数据存储在对象的width,height,area属性中 '''
15.其他函数 1 2 3 hasattr ()函数用于检查对象是否拥有指定名称的属性,返回布尔型setattr ()函数给对象设定属性及其值。getattr ()函数则用于获取对象指定名称的属性的值,如果属性不存在,返回第三个参数给定的默认值。
16.类型的注解
变量的类型注解
1 2 3 4 5 6 7 8 9 10 11 语法: 变量: 类型 a:int = 10 b:float = 20.0 class Student : pass stu:Student = Student() li:list [int ] = [1 ,2 ,3 ,4 ] li2:list [int ,float ] = [1 ,2.1 ]
函数(方法)的类型注解
1 2 3 4 5 6 方法的注解: def fun (a:int ,b:int ): pass def fun2 (a:int ,b:int ) -> int : pass
Union注解
1 2 from typing import unionli:list [union[str ,int ,float ]] = [1 ,1 ,1.2 ,8.2 ,"hello" ]
第九章 字符串进阶 1.浅尝辄止 字符串的字典映射替换:
1 2 sText = "name:{},age:{age},sex:{sex}" .format ("小明" ,age=20 ,sex="male" ) print (sText)
1 2 3 dro = {"name" :"小明" ,"age" :20 } s = "name:{name},age:{age}" print (s.format_map(dro))
2.替代字段 1 2 3 4 5 6 7 score = 97 print (f"score={score:10.2 f} " )''' {score:10.2f} 为替代字段 score 为替代字段名 :后面部分 格式说明符 '''
说明符
含义
b
整数以二进制展现。
c
整数按Unicode码转成对应符号,请试:”{num:c}”.format(num=0x1f60a)
d
整数以十进制展现,如果格式说明符被省略,整数默认为十进制
o
整数以八进制展现(字母小o,不是数字0)
x
整数以十六进制展现且使用小写字母
X
整数以十六进制展现但使用大写字母
e
整数/浮点数使用科学计数法展现,使用e表示指数
E
整数/浮点数使用科学计数法展现,使用E表示指数
f
整数/浮点数以定点小数展现,比如3.14,特殊值nan和inf,用小写表示。nan表示非数-not a number, inf表示正无穷,inf表示负无穷。
F
同f,但对于特殊值NAN和INF,使用大写表示
g
系统自行选择使用定点小数或者科学计数法表示整数/浮点数
G
同g,但用大写字符表示指数及特殊值
n
同g, 但插入数字分隔符
s
字符串以字符串原始形式展现
%
整数/浮点数以百分比展示
3.宽度、精度及分结符 1 2 3 4 5 6 7 8 9 10 11 {pi:10.2 f},说明定点小数宽度10 ,精确到小数点第2 位 {num:10 },说明整数宽度10 ,打印结果中明显看到1024 前的空格。 {:.5 },取了字符串的前5 个字符。 {:,},十进制整数中使用逗号作为千位分节符。 {pi:010.2 f},宽度10 ,精度2 ,10 前的0 表示补0 。 {pi:<10.2 f},<表示左对齐。 {pi:^10.2 f},^表示居中。 {pi:@>10.2 f},>表示右对齐,使用特殊字符@来填充。 {0 :+10.2 f},使用第0 个参数,+号表示要显示正号。 {1 :=+10.2 f},使用第1 个参数,=号表示通过在符号位和数之间插入填充字符(空格)来满足10 位宽度。
4.其他函数
1 2 3 4 5 6 7 8 9 10 11 12 13 14 s.find("to" ,0 ,len (s))试图在s中找"to" 第一次出现的位置下标,如果找不到,返回-1 。参数2 ,3 指明了搜索的开始下标和结束下标(不含结束下标),参数2 ,3 可省略。 rfind() - 找字符串中指定的子串的最后一次出现的位置下标; index() - 找指定子串的第一次出现的位置下标,找不到引发异常; rindex() - 找最后一个子串的索引,找不到引发异常; count() - 统计子串出现次数; startswidth() - 是否以子串开头; endswidth() - 是否以子串结尾。
1 2 s.join(seq)中,s为指定的间隔字符串,seq可以是元组或者列表,但其中的元素必须是字符串
1 2 sText.replace(old,new,count=-1 )将字符串内的指定子串全部替换成另一个指定子串,不会导致sText被修改,函数会返回一个新的字符串作为结果。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 split()函数的作用与join()函数相反,把一个字符串用指定的间隔符拆开成多个字符串,并放入一个列表中返回。 相关函数: partition(sep)-使用子串划分字符串,返回一个元组,包括三个字符串:sep前的部分,sep,sep后的部分; seq=“stringsthbig” s=seq.partition(“sth”) s的结果为('string' , 'sth' , 'big' ) rpartition(sep)-同partition(sep),搜索方向为右向左; rsplit()-同split(),方向右向左; splitlines()-分拆字符串为多行。 translate()-借助于转换表实现字符串内单字符的快速替换; is 系列函数,用于判断字符串是否具备某种特性,比如仅包含数字,全是大写之类:isspace(), isdigit(),isupper(),islower(),isdecimal(), isidentifier(),isnumeric(),isprintable(),istitle()。
第十章 文件读写 1.基本操作 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 f = open ("datafile.txt" ,"w" ) f.write("This is a file which is writable in text mode.\n" ) f.write("'w' means open file in write mode.\n" ) f.close() f = open ("datafile.txt" ,"r" ) sLine1 = f.readline() sLine2 = f.readline() print (sLine1,sLine2)f.close() """ open(file,mode,encoding='utf-8')函数用于打开一个文件,其中,file参数用于指定操作文件名,该文件名既可以是绝对路径,比如"d:\\Python\\Test\\test.dat",也可以是相对路径,比如"data\\test.dat" close(f)用于关闭已打开的文件f,好处有: 1.减少操作系统I/O资源占用; 2.避免因缓存/意外错误导致文件没有成功写入甚至损坏。 如果不想关闭文件,同时又希望确保将缓存中的数据写入文件,可以执行f.flush()函数。 f.read()函数从文件读出全部内容并以字符串形式(文本模式时)返回 f.read(5)则从文件读出5个字符 f.readline()则从文件读出一行 f.readlines()读取全部行,得到列表 f.writeline()则负责向文件写入一行 f.write()用于文件写入数据 直接调用f.write,内容并未真正写入文件,而是会积攒在程序的内存中,称之为缓冲区 当调用f.flush的时候,内容会真正写入文件 with open() as f 通过with open语法打开文件,可以自动关闭 """
mode参数:
文件模式
说明
“r”
读模式(默认)
“w”
写模式
“x”
独占写模式,这意味着不允许其它应用程序在该文件关闭前使用该文件; x来源于英文ex clusive-独占。
“a”
附加模式 - append
“b”
二进制模式,与其它模式配用
“t”
文本模式(默认)
“+”
读写模式,必须与r,w,a等配合使用
1 2 3 4 5 6 当open ()函数省略了文件模式参数时,默认为"rt“ 以 " w"或" w+"模式打开文件时,如果文件不存在,会自动新建一个 " wb"以写模式打开一个二进制文件," rb"则以读模式打开一个二进制文件。如果又想读,又想写,可以使用" wb+"或者" rb+"。
2.随机存取 文件可以看作是一个流(stream)。在流中,每一个元素(对于二进制文件而言,以字节为单位关)都有地址,这个地址称为偏移量(offset).
系统允许跳到某个特定偏移量读取或写入。写入时,该偏移量开始的文件原内容会被覆盖。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 import iof = open ('randomaccess.txt' ,"w+" ) sText = "" .join((str (x) for x in range (30 ))) f.write("汉" + sText) f.seek(6 ) f.write("OFFSET_6_" ) print ("Current file position after seek and write:" , f.tell())f.close() f = open ('randomaccess.txt' ,"r" ) print ("Content:" )print (f.read())f.close() """ seek(offset,whence=io.SEEK_SET)函数: whence表明偏移量的参照物:io.SEEK_SET(值为0) - 相对于文件开头偏移,此时偏移量当为正数; io.SEEK_END (值为2) - 相对于文件尾偏移,此时偏移量当为负数; io.SEEK_CUR (值为1) - 相对于当前读写位置偏移,此时偏移量可为正数或负数。 当文件以文本模式工作时,seek()无法相对文件尾或者当前读写位置偏移。 """
3.标准输入,输出及错误流 和UNIX操作系统的概念很像
1 2 3 4 5 6 7 sys.stdin : 标准输入,对应于键盘/控制台输入,使用input ()函数读取操作者输入时,数据即可认为“读取”自sys.stdin sys.stdout : 标准输出,对应于显示器/控制台输出,使用print ()函数打印信息时,可视作数据被"写入" 至sys.stdout sys.stderr : 标准错误,程序产生错误时,报错信息则被输出给sys.stderr,默认情况下,sys.stderr也对应显示器/控制台输出
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 import sysf = open ('input.txt' ,'w' ) f.write("Alex\n" ) f.write("27\n" ) f.close() fIn = open ('input.txt' ,"r" ) sys.stdin = fIn fOut = open ('output.txt' ,"w" ) sys.stdout = fOut fError = open ('error.txt' ,'w' ) sys.stderr = fError sName = input ("What's your name?" ) iAge = int (input ("How old are you?" )) print ("Hi," , sName.title(), "You are {} year's old." .format (iAge))fIn.close() fOut.close() raise Exception("ERROR INFO" )fError.close() """ 将sys.stdin, sys.stdout, sys.stderr重定向: sys.stdin = fIn sys.stdout = fOut sys.stderr = fError """
4.文件内容迭代 1 2 3 4 5 6 7 8 9 10 with open ('title.txt' ) as f: while True : char = f.read(1 ) if not char: break process(char) """ read(1)每次从文件中读取一个字符,当读到文件尾时,返回空。按照非空即真,空即是假的原则,到达文件尾时,break语句将执行,循环结束,文件被自动关闭。 """
1 2 3 4 5 6 7 8 9 10 with open ('title.txt' ) as f: for x in f.readlines(): process(x) with open ('title.txt' ) as f: for line in f: print (line)
5.json文件格式 json的全称为JavaScript Object Notation ,是一种轻量级的跨语言、跨平台数据交换格式
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 import jsondora = {"name" :"Dora CHEN" , "no" :"2018173" , "age" :26 ,"married" :False , "scores" :[{"C++" :76 },{"Data Structure" :99.5 },{"Home Econoics" :62 }]}with open ("dora.json" ,"w" ) as f: json.dump(dora,f) with open ("dora.json" ) as f: doraLoaded = json.load(f) for key,value in doraLoaded.items(): print (key,":" , value) """ json模块和dump()函数把一个嵌套的字典以及内部列表,甚至列表内部的字典序列化并存储至一个文本文件: dora.json。 """
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 import jsondora = {"name" :"Dora CHEN" , "no" :"2018173" , "age" :26 ,"married" :False , "scores" :[{"C++" :76 },{"Data Structure" :99.5 },{"Home Econoics" :62 }]}with open ("dora.json" ,"w" ) as f: json.dump(dora,f) with open ("dora.json" ) as f: doraLoaded = json.load(f) for key,value in doraLoaded.items(): print (key,":" , value) """ 借助于load()函数,从dora.json文件复原了一个doraLoaded字典 """
第十一章 异常处理及单元测试 1.遇到过的异常
异常类
说明
ValueError
值与期望的不符
IndentationError
代码缩进错误
IndexError
序列索引不存在
AssertionError
断言失败
NameError
名字不存在
KeyError
映射(比如字典)中的键不存在
AttributeError
属性错误(对象无指定名字的属性)
TypeError
类型出错
SyntaxError
代码语法错误
OSError
操作系统未能执行指定任务
ZeroDivisionError
除0错误
异常发现后的处理:
捕获并处理异常,尝试将程序从异常中拯救出来,继续正常运行。
捕获并处理异常,至少做一些必要的紧急操作,避免严重后果的发生。
捕获并处理异常,将异常信息保存在错误日志中,以便程序员查找错误发生的原因。
2.异常处理 try-except-else-finally语句
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 def divide (a, b ): return a/b while True : sFirst = input ("First number:" ) sSecond = input ("Second number:" ) if sFirst == "q" or sSecond == "q" : break try : iFirst = int (sFirst) iSecond = int (sSecond) fResult = divide(iFirst,iSecond) except (ZeroDivisionError) as e: print ("You can not divide by 0:" ,e) except (ValueError,TypeError) as e: print ("Illegal value been inputted:" ,e) print (type (e)) except (Exception) as e: print ("An exception found, I do not know how to process it." ) raise else : print ( sFirst, "/" , sSecond, "=" , fResult) finally : print ("'Finally' will be executed what ever happens." ) """ 1.首先,解释器将会执行try子句内的代码 2.try子句的执行没有发生异常,在try子句执行完毕后将执行else子句,然后再执行finally语句 3.如果try子句的执行发生了异常,将从前往后逐一检查except子句括号里所包括的异常类型,当实际发生的异常属于该except子句括号内的异常类型时,该except子句将会被执行。最后,finally子句也会被执行。 4.如果捕获的异常在当前情境下处理不了,也可以接着向外抛:raise即为该用途。如果直接raise,抛出的是原有异常。 try: iFirst = int(sFirst) iSecond = int(sSecond) fResult = divide(iFirst,iSecond) except: print("You can not divide by 0:",e) except (NameError, ZeroDivisionError): print('ZeroDivision错误...') """
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 ''' 当函数func01中发生异常, 并且没有捕获处理这个异常的时候, 异常 会传递到函数func02, 当func02也没有捕获处理这个异常的时候 main函数会捕获这个异常, 这就是异常的传递性. ''' def func1 (): print ("func1 开始执行" ) num = 1 / 0 print ("func1 结束执行" ) def func2 (): print ("func2 开始执行" ) func1() print ("func2 结束执行" ) def main (): try : func2() except Exception as e: print (f"出现异常了,异常的信息是:{e} " ) main()
3.警告 1 2 3 4 5 6 7 8 9 10 11 12 from warnings import warndef divide (a,b ): fResult = a / b if fResult < 0.0000001 : warn("The result is very close to Zero!" ) return fResult print (divide(0.1 , 10000000000 ))print ("Something else." )""" warn()函数发出了警告,并把警告打印至屏幕,但程序的执行不会因为该警告而停止:print("Something else.")在警告之后继续执行了。 """
第十二章 python的模块和包 1.模块
2.包
什么是包
1 2 3 从物理上看,包就是一个文件夹,在该文件夹下包含了一个 __init__.py 文件,该文件夹可用于包含多个模块文件 从逻辑上看,包的本质依然是模块 注意:新建包后,包内部会自动创建`__init__.py`文件,这个文件控制着包的导入行为
导入包
1 2 3 4 5 6 7 8 9 1.方式一 import 包名.模块名 包名.模块名.目标 2.方式二 注意:必须在`__init__.py`文件中添加`__all__ = []`,控制允许导入的模块列表 from 包名 import * 模块名.目标
安装第三方包
1 pip install -i https://pypi.tuna.tsinghua.edu.cn/simple 包名称
第十三章 python高阶技巧 1.闭包 在函数嵌套的前提下,内部函数使用了外部函数的变量,并且外部函数返回了内部函数,把这个使用外部函数变量的内部函数称为闭包。
优点:
无需定义全局变量即可实现通过函数,持续的访问、修改某个值
闭包使用的变量的所用于在函数内,难以被错误的调用修改
缺点:
由于内部函数持续引用外部函数的值,所以会导致这一部分内存空间不被释放,一直占用内存
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 def outer (logo ): def inner (msg ): print (f"<{logo} >{msg} <{logo} >" ) return inner fn1 = outer("黑马程序员" ) fn1("大家好" ) fn2 = outer("传智教育" ) fn2("大家好" ) def outer (num1 ): def inner (num2 ): nonlocal num1 num1 += num2 print (num1) return inner fn = outer(10 ) fn(10 ) fn(10 ) fn(10 ) fn(10 ) def account_create (initial_amount=0 ): def atm (num, deposit=True ): nonlocal initial_amount if deposit: initial_amount += num print (f"存款:+{num} , 账户余额:{initial_amount} " ) else : initial_amount -= num print (f"取款:-{num} , 账户余额:{initial_amount} " ) return atm atm = account_create() atm(100 ) atm(200 ) atm(100 , deposit=False )
2.装饰器 装饰器:也是一种闭包, 其功能就是在不破坏目标函数原有的代码和功能的前提下,为目标函数增加新功能。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 def outer (func ): def inner (): print ("我睡觉了" ) func() print ("我起床了" ) return inner def sleep (): import random import time print ("睡眠中......" ) time.sleep(random.randint(1 , 5 )) fn = outer(sleep) fn() def outer (func ): def inner (): print ("我睡觉了" ) func() print ("我起床了" ) return inner @outer def sleep (): import random import time print ("睡眠中......" ) time.sleep(random.randint(1 , 5 )) sleep()
3.设计模式 设计模式是一种编程套路,可以极大的方便程序的开发。最常见、最经典的设计模式,就是我们所学习的面向对象了。
除了面向对象外,在编程中也有很多既定的套路可以方便开发,称之为设计模式:
1.单例模式 单例模式(Singleton Pattern)是一种常用的软件设计模式,该模式的主要目的是确保某一个类只有一个实例存在。在整个系统中,某个类只能出现一个实例时,单例对象就能派上用场。
定义:
保证一个类只有一个实例,并提供一个访问它的全局访问点
适用场景:当一个类只能有一个实例,而客户可以从一个众所周知的访问点访问它时。
优点:
1 2 3 4 5 6 class StrTools : pass str_tool = StrTools()
1 2 3 4 5 6 7 8 9 from str_tools_py import str_tools1 = str_tool s2 = str_tool print (id (s1))print (id (s2))
2.工厂模式 当需要大量创建一个类的实例的时候, 可以使用工厂模式。即从原生的使用类的构造去创建对象的形式迁移到,基于工厂提供的方法去创建对象的形式。
优点:
大批量创建对象的时候有统一的入口,易于代码维护
当发生修改,仅修改工厂类的创建方法即可
符合现实世界的模式,即由工厂来制作产品(对象)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 class Person : pass class Worker (Person ): pass class Student (Person ): pass class Teacher (Person ): pass class PersonFactory : def get_person (self, p_type ): if p_type == 'w' : return Worker() elif p_type == 's' : return Student() else : return Teacher() pf = PersonFactory() worker = pf.get_person('w' ) stu = pf.get_person('s' ) teacher = pf.get_person('t' )
后记 写到这里,基本上是把python的语法笔记写完了。最开始,我还以为就能够2天写完,没想到重新学了一遍收获颇多,大大小小花了两周多的时间。就例如OO 程序设计,在平常用来学习写的代码,几乎是用不到的,这也以为着遗忘也是必然的。所以,希望这一片文档能够,快速帮我复习python的语法。
当然,对于教材后面的Numpy等知识点,还是去看前言中的视频。当然等有需要的时候,在去写数据分析与可视化的笔记。