文章目录
- >知识点详解及一些题目练习
- >常用库及其使用方法
- >常用知识点
- >常见报错以及基本解决方法
- 1 - PermissionError
- 2 - FileNotFoundError
- 3 - SyntaxError 之 invalid syntax
- 4 - AttributeError
- 5 - OSError
- 6 - NameError
- 7 - AssertionError
- 8 - No such file or directory
- 9 - SyntaxError 之 position argument follows keyword argument
- 10 - IndexError
- 11 - TypeError
- 12 - UnboundLocalError
- 13 - UnicodeDecodeError
- 14 - KeyError
- >其他好物
>知识点详解及一些题目练习
>知识点
>分支结构知识点
#单分支结构,由一个if组建的分支结构
#格式为
# if <判断条件> :
# <语句块>
print("------------(单分支结构)--------------")
a = int(input("请输入一个数"))
if a % 2 == 0:
print("该数为偶数")
print("----------------------------------------")
#二分支结构/双分支结构,由if……else组建的分支结构
#格式为
# if <判断条件>:
# <语句块1>
# else:
# <语句块2>
print("------------(二分支结构)--------------")
a = int(input("请输入一个数"))
if a % 2 == 0:
print("该数为偶数")
else:
print("该数为奇数")
print("----------------------------------------")
#多分支结构,由if……elif……else组建的分支结构
#格式为
# if <判断条件1>:
# <语句块1>
# elif <判断条件2>:
# <语句块2>
# else:
# <语句块3>
print("------------(多分支结构)--------------")
a = int(input("请输入你的年龄"))
if a < 18:
print("您小于18岁")
elif 18 < a < 30:
print("您大于18岁,但小于30岁")
else:
print("您大于30岁")
print("----------------------------------------")
#分支结构的嵌套,分支结构可以嵌套,可以包含多个分支结构
#格式为
# if <判断条件1>:
# <语句块1>
# if <判断条件2>:
# <语句块2>
# else:
# <语句块3>
# else:
# <语句块4>
print("-----------(分支结构嵌套)-------------")
a = int(input("请输入你的年龄"))
if a < 18:
print("您小于18岁")
else:
if 18 < a < 30:
print("您大于18岁,但小于30岁")
else:
print("您大于30岁")
print("----------------------------------------")
>基础标准函数学习
# min() 获取最小值函数,可以求得两数或一个列表中的最小值
print("----------min----------")
a = [1,2,3,4,5]
print("列表{}中最小数为{}".format(a,min(a) ) )
# max() 获取最大值函数,可以求得两数或一个列表中的最大值
print("----------max----------")
a = [1, 2, 3, 4, 5]
print("列表{}中最小数为{}".format(a, max(a) ) )
# sum() 求总和
print("----------sum----------")
a = [1, 2, 3, 4, 5]
print("列表数总和为{}".format(sum(a) ) )
# eval() 转换表达式,对字符串进行处理,相当于直接去除字符串的引号
print("----------eval---------")
a = "1+2+3"
b = eval(a) #eval()去除引号相当于是1+2+3=6,所以最后结果是6
print("转换后为{}".format(b) )
# len() 获取列表、字典、字符串、元组、集合的长度,不能获取数字长度
print("----------len----------")
a = [1, 2, 3, 4, 5]
print("列表长度为{}".format(len(a) ) )
# round() 保留n位小数,取四舍五入后的结果
# 注意!如果round()直接传入数值,则直接四舍五入到整数部分
print("---------round---------")
a = 1.234
print("1.234保留两位小数后是{}".format(round(a,2) ) )
b = 1.234
print("1.234直接传入round后得{}".format(round(a) ) )
# pow() 幂运算,pow(x,y)得到x的y次方
print("----------pow----------")
a = pow(2,3)
print("2的3次方为{}".format(a))
# range() 范围函数,后面可以加上一个、两个、或三个参数
# 一个参数时,表 0 ~ x-1
# 以下打印结果,我转换成列表,便于观看
print("-------range(x)--------")
a = list(range(5))
print("range(5)为{}".format(a))
# 两个参数时,表 x ~ y-1
print("------range(x,y)-------")
a = list(range(1,5))
print("range(1,5)为{}".format(a))
# 三个参数时,表 x ~ y-1,每z个取一个
print("-----range(x,y,z)------")
a = list(range(1, 5, 2))
print("range(1,5,2)为{}".format(a))
>random随机库学习
import random
#random.randint(a,b)
#randint 括号中写两个数字,表示随机a~b之间的随机【整数】
print("----------randint----------")
a = random.randint(1,3)
print("随机数为",a)
#random.choice(List)
# choice 括号中接上一个列表,表示从【列表】中随机取一个
print("----------choice----------")
List = [1,2,3,4,5]
a = random.choice(List)
print("随机数为",a)
#random.choices(List,k = n)
# choices 括号中除了列表,还可以多加一个数值,表示从【列表】中随机n次取值,最后返回一个列表
#注意!这里在设置n次取值时,是 k = n的格式!
print("----------choices----------")
List = [1,2,3,4,5]
a = random.choices(List,k = 2)
print("随机数为",a)
#random.random()
# random 括号中不需要加东西,表示随机选择0-1之间的【浮点数(小数)】
#注意!包含0,但不包含1
print("----------random----------")
a = random.random()
print("随机数为",a)
#random.uniform(a,b)
# uniform 括号中写两个数字,表示随机a~b之间的随机【浮点数】
print("----------uniform----------")
a = random.uniform(1,3)
print("随机数为",a)
#random.sample(List,n)
# sample,括号中写两个数据,一个是要随机取值的列表,一个是随机取值的个数
#注意!这里在设置随机取值的个数的时候,可以直接写数值,也可以使用 k = n的格式
print("----------sample----------")
List = [1,2,3,4,5]
a = random.sample(List,2)
print("随机数为",a)
#random.shuffle(List)
# shuffle,括号中加上一个列表,表示随机打乱列表的顺序,但有一点要注意,shuffle之后是没有返回值的!
print("----------shuffle----------")
List = [1,2,3,4,5]
a = random.shuffle(List)
print("shuffle没有返回值")
>循环学习
#普通循环
# # 循环变量i从0开始不断递增,range()里的数字代表循环执行的次数
for i in range(3):
print(i)
# 进阶循环
# range()传入2个数字,第一个代表的是起点(不传入默认为0),第二个代表的是终点(不包含这个数)。
for i in range(1, 3):
print(i)
#range()传入3个数字,第一个是起点,第二个是终点,第三个是步长间距。
for i in range(1, 10, 2):
print(i)
#循环结合列表,会按照顺序一个一个的取到列表里的元素,把它放到i里面(第一次循环取到列表里的第一个元素,此时i里面就存放的列表第一个元素)
#举例:列表中的元素可以想象成一群排好队的小朋友,i是当天做值日的同学
# 第一天是第一个同学值日,所以第一次循环,i是列表中第一个元素,第二天是第二个同学值日,第二次循环,i是列表中的第二个元素
for i in [1, 2, 3, 4]:
print(i)
for i in ['a', 'b', 'c']:
print(i)
#循环结合字符串,规则和上面列表一模一样,字符串当中的每一个字符成员都可以按照顺序取出来
for i in "12345":
print(i)
#break退出循环
i = 0
while i < 5:
i += 1
print(i)
if i == 2:
break
#continue跳过本轮循环开始下一次
i = 0
while i < 5:
i += 1
print(i)
if i == 2:
print("continue之前的语句可以被执行")
continue
print("continue之后的语句无法被执行")
>递归方法求解阶乘
def fac(n):
if n < 2:
return 1
else:
return n*fac(n-1)
def Fsum(n):
if n == 1:
return 2
elif n == 0:
return 1
else:
return fac(n)+Fsum(n-1)
num = int(input("请输入一个正整数"))
print(Fsum(num))
>函数方法求解阶乘
import math
a = int(input("请输入一个正整数"))
b = 0
for i in range(a+1):
b += math.factorial(i)
print(b)
> 练习题及刷题网站(答案不唯一,仅提供一种参考喔~)
>刷题网站
→ 洛谷刷题系统(可以刷不同语言题目):
https://www.luogu.com.cn/
>练习题
>1.求水仙花数
(一)求水仙花数
num = input("请输入一个正整数,范围为500-1000:")
if int(num[0])**3 + int(num[1])**3 + int(num[2])**3 == int(num):
print(num,"是一个水仙花数")
else:
print(num,"不是一个水仙花数")
>2.M\N组合数
(二)M、N组合数
N = int(input("请输入一个正整数"))
M = input("请输入若干个不同的正整数,由逗号分隔").split(",")
count = 0
for i in range(len(M)):
for j in range(i+1,len(M)):
if int(M[i])+int(M[j]) == N:
count += 1
print("{}+{}={}".format(M[i], M[j],N))
print("组合数有",count,"种")
>3.辗转相除法求最小公倍数
a=int(input("第一个数"))
b=int(input("第二个数"))
a1 = a
b1 = b
res = a1 % b1
while res != 0:
a1 = b1
b1 = res
res = a1 % b1
print("最小公倍数为:",int(a*b/b1))
>4.求两个数的公约数个数
a = int(input("第一个数字:"))
b = int(input("第二个数字:"))
c = 0
for i in range(1,max(a,b)+1):
if a%i == 0 and b%i == 0:
c += 1
print(c)
>5.摘苹果问题
(五)摘苹果问题
N = int(input())
ls = list(map(int,input().split(",")))
cnt = 0
for i in ls :
if i <= N+80 :
cnt += 1
print(cnt)
>6.判断互质数
(六)判断互质数
ls = list(map(int, input().split(",")))
m = ls[0]
n = ls[1]
count = 0
list_m = [] # m的因数存储列表
list_n = [] # n的因数存储列表
for i in range(2, m+1):
if m % i == 0:
list_m.append(i) # m的因数用列表存放起来
for i in range(2, n+1):
if n % i == 0:
list_n.append(i) # n的因数用列表存放起来
for i in list_m:
if i in list_n:
count += 1 # 公约数计数
if count == 0:
print("yes")
else:
print("no")
>7.判断N-M路线数
(七)如图:判断N-M路线数
ls = list(map(int, input().split(" ")))
N = ls[0]
M = ls[1]
k = M-N+1 # 将n,m相对距离,转化成1~k的距离
def search(x):
if x == 1 or x == 2:
return 1
return(search(x-1) + search(x-2))
print(search(k))
>8.污染海域问题
(八)污染海域问题
n, m = eval(input())
ls = []
ls.append([0 for i in range(m+1)])
for i in range(n):
l = list(map(int, input().split(",")))
ls.append([0]+l)
cnt = 0
for i in range(1, n+1):
for j in range(1, m+1):
if ls[i][j] == 1:
ls[i][j] = -1
if ls[i-1][j] == -1 or ls[i][j-1] == -1:
continue
else:
cnt += 1
print(cnt)
>9.搬运问题
(九)搬运问题
def f(n):
if n == 1 :
return 1
elif n == 2:
return 2
elif n == 3 :
return 4
else:
return f(n-1)+f(n-2)+f(n-3)
N = int(input())
print(f(N))
>10.冰雹猜想
(十)冰雹猜想
冰雹猜想是指对于任意正整数n,如果它是偶数,那么就将它除以2,如果是奇数,那么就将它乘以3加1,然后得到一个新的整数。重复这个过程直到最后得到的结果为1。之所以称为猜想,是因为无论初始值是什么,这个过程最终都会得到1。这个猜想在数学界也被称为科拉兹猜想,它一直未被证明或者推翻。尝试用代码演算一下冰雹猜想吧!
n= int(input("请输入一个正整数:"))
if n <= 0:
print("请输入一个正整数!!")
else:
while n != 1:
if n % 2 == 0:
n = n // 2
else:
n = n * 3 + 1
print(n,end=" ")
print("\n冰雹猜想结束,最终结果为:",n)
>常用库及其使用方法
一、海龟库
#导入
import turtle
》》1.创建画笔
mypen = turtle.Pen()
#mypen是画笔名称,这里可以自己命名,怎么定义名称,后续就怎么使用
》》2.固定画布
turtle.done()
二、随机库
》》导入
import random
random.randint(a,b)
randint 括号中写两个数字,表示随机a~b之间的随机【整数】
random.choice(List)
#choice 括号中接上一个列表,表示从【列表】中随机取一个
random.choices(List,k = n)
#choices 括号中除了列表,还可以多加一个数值,表示从【列表】中随机n次取值,最后返回一个列表
注意!这里在设置n次取值时,是 k = n的格式!
random.random()
#random 括号中不需要加东西,表示随机选择0-1之间的【浮点数(小数)】
注意!包含0,但不包含1
random.uniform(a,b)
#uniform 括号中写两个数字,表示随机a~b之间的随机【浮点数】
random.sample(List,n)
#sample,括号中写两个数据,一个是要随机取值的列表,一个是随机取值的个数
注意!这里在设置随机取值的个数的时候,可以直接写数值,也可以使用 k = n的格式
random.shuffle(List)
#shuffle,括号中加上一个列表,表示随机打乱列表的顺序,但有一点要注意,shuffle之后是没有返回值的!
三、json库
》》导入
import json
》》读取json
读取json 括号中加上要读取的json文件
json.load(file)
》》写入json
写入json 括号中加上(需要写入的内容,写入的文件)
json.dump(content,file)
四、pyecharts库
》》导入柱状图
from pyecharts import Bar
》》导入饼状图
from pyecharts import Pie
》》导入折线图
from pyecharts import Line
》》导入雷达图
from pyecharts import Radar
》》导入漏斗图
from pyecharts import Funnel
》》导入河流图
from pyecharts import ThemeRiver
》》导入词云图
from pyecharts import WordCloud
》》导入散点图
from pyecharts import Scatter
五、PyQt5
》》PyQt5 QLabel控件
PyQt5 QLabel控件
>常用知识点
1 - 变量的命名规则
规则一:变量区分大小写,如:A和a是两种变量名;
规则二:可以使用字母;
规则三:可以加下划线;
规则四:可以加数字,但数字不能放在最前面。
2 - 逻辑/布尔运算(and、or、not)
>and
and 表示【和】,由and连接的条件,全对为对(√ and √才能对)
举例:
10大于1,并且9大于3,两个条件都满足,则为True(正确)
>or
or 表示【或者】,由or连接的条件,有一个是对的,那就是对的
举例:
10大于1,或者9小于3,至少有一个条件都满足,则为True(正确);
10小于1,或者9大于3,至少有一个条件都满足,则为True(正确)
>not
not,表示【非】,非表示的就是反义,正确的反义就是错误
举例:
10>9,所以可以打印第一个判断,
not 10>9,相当于 10 ≤ 9 ,咋可能呢?~
注意!
当同时存在and和or的时候,先计算and,再计算or。有括号的话,还是先算括号内容!
判断相等是两个等于,如:要判断A和B的值是不是相等的,应该:
if A == B :
xxx
3 - 变量的自增、自减、自乘、自除
x += y → x = x + y
x -= y → x = x - y
x *= y → x = x * y
x /= y → x = x / y
4 - range的奥秘
range表范围,后面可以加上1、2或者3个数据 (这里为了便于观看打印结果,我转换成列表)
>range(x)
表示从0~x-1
>range(x,y)
表范围,表示从x~y-1
>range(x,y,z)
表示从x~y-1,每z个取一个,这里的z也被称作“步长”
5 - if name == “main”:
每个python模块都包含内置的变量__name__。(__name__是python的一个内置类属性,它天生就存在于一个python程序中,代表对应程序名称),当运行模块被执行的时候,__name__等于当前执行文件的名称【模块名】(包含了后缀.py),“main”等于当前执行文件的名称【模块名】(包含了后缀.py)。进而当模块被直接执行时,name == 'main’结果为真。如果把py当做一个模块import到其他代码中,则__name__等于模块名称(不包含后缀.py)
6 - for循环的常用格式
>for i in range:
for i in range()一般表示在某一个范围内循环,(具体范围见【常用知识点4】),一般都会有一个固定的循环次数。
>for i in 列表:
当咱们for在使用时,直接循环一个列表的话(注意,这里就不会用到范围range了),是直接从左往右循环列表中的内容,循环次数则为列表的长度!
7 - 切片
切片可以截取出列表、元组、字符串中的部分元素
- 一个完整的切片表达式包含两个“:”(冒号),用于分隔三个参数:(起始索引:终止索引:步长)。
- 需要注意的是:切片是一个前闭后开的区间。(包头不包尾)
- 注意,索引从0开始!!!
- 不写步长时默认为 1 ,可以指定步长。
- 步长为正数的时候方向为从左往右切,步长为负数的时候方向为从右往左切。
下面以一个列表 List = [“A”,“B”,“C”,“D”,“E”,“F”] 为例
(一)List[起始索引:]
从起始索引位置开始截取字符串,截取到List最后一个元素
(二)List[:终止索引]
从列表最开头开始截取字符串,截取到终止索引,注意,不包括终止索引
(三)List[起始索引:终止索引]
从起始索引位置开始截取字符串,截取到终止索引,注意,不包括终止索引
(四)List[起始索引:终止索引:步长]
从起始索引位置开始截取字符串,每隔步长个单位取一个元素,截取到终止索引,注意,不包括终止索引
8 - 正则表达式(具体re模块见知识点9)
re模块是python独有的匹配字符串的模块,该模块中提供的很多功能是基于正则表达式实现的,而正则表达式是对字符串进行模糊匹配,提取自己需要的字符串部分,他对所有的语言都通用。注意:
- re模块是python独有的
- 正则表达式所有编程语言都可以使用
- re模块、正则表达式是对字符串进行操作
因为,re模块中的方法大都借助于正则表达式,故先学习正则表达式。
(一)常用正则
1、字符组
在同一个位置可能出现的各种字符组成了一个字符组,在正则表达式中用[ ]表示
2、字符
3、量词
(二)正则表达式的使用
1、. ^ $
2、* + ? { }
注意:前面的*,+,?等都是贪婪匹配,也就是尽可能匹配,后面加?号使其变成惰性匹配
3、字符集[][^]
4、分组 ()与 或 |[^]
身份证号码是一个长度为15或18个字符的字符串,如果是15位则全部由数字组成,首位不能为0;如果是18位,则前17位全部是数字,末位可能是数字或x,下面我们尝试用正则来表示:
5、转义符(反斜杠\)
在正则表达式中,有很多有特殊意义的是元字符,比如\n和\s等,如果要在正则中匹配正常的"\n"而不是"换行符"就需要对"“进行转义,变成’\'。
在python中,无论是正则表达式,还是待匹配的内容,都是以字符串的形式出现的,在字符串中\也有特殊的含义,本身还需要转义。所以如果匹配一次”\n",字符串中要写成’\n’,那么正则里就要写成"\\n",这样就太麻烦了。这个时候我们就用到了r’\n’这个概念,此时的正则是r’\n’就可以了。
6、贪婪匹配
贪婪匹配:在满足匹配时,匹配尽可能长的字符串,默认情况下,采用贪婪匹配
几个常用的非贪婪匹配Pattern:
*? 重复任意次,但尽可能少重复
+? 重复1次或更多次,但尽可能少重复
?? 重复0次或1次,但尽可能少重复
{n,m}? 重复n到m次,但尽可能少重复
{n,}? 重复n次以上,但尽可能少重复
.*?的用法
9 - re模块
(一)常量、属性
1、re.A(re.ASCII)
让\w,\W,\b,\B,\d,\D,\s和\S 执行ASCII-只匹配完整的Unicode匹配代替。这仅对Unicode模式有意义,而对于字节模式则忽略。
2、re.I(re.IGNORECASE)
执行不区分大小写的匹配;类似的表达式也[A-Z]将匹配小写字母。
3、re.L(re.LOCALE)
让\w,\W,\b,\B和区分大小写的匹配取决于当前的语言环境。该标志只能与字节模式一起使用。不建议使用此标志,因为语言环境机制非常不可靠,它一次只能处理一种“区域性”,并且仅适用于8位语言环境。默认情况下,Python 3中已为Unicode(str)模式启用了Unicode匹配,并且能够处理不同的语言环境/语言。
4、re.M(re.MULTILINE)
指定时,模式字符’‘在字符串的开头和每行的开头(紧随每个换行符之后)匹配;模式字符’‘在字符串的末尾和每行的末尾(紧接在每个换行符之前)匹配。默认情况下,’’ 仅在字符串的开头,字符串’‘在字符串的末尾和每行的末尾(紧接在每个换行符之前)匹配。默认情况下,’^’ 仅在字符串的开头,字符串’‘的末尾和字符串末尾的换行符(如果有)之前立即匹配。
5、re.S(re.DOTALL)
使’.‘特殊字符与任何字符都匹配,包括换行符;没有此标志,’.'将匹配除换行符以外的任何内容。
(二)常用方法
1、re.compile(pattern,flags = 0 )
将正则表达式模式编译为正则表达式对象,可使用match(),search()以及下面所述的其他方法将其用于匹配》》prog = re.compile(‘\d{2}’) # 正则对象
》》prog.search(‘12abc’)
<_sre.SRE_Match object; span=(0, 2), match=‘12’>
》》prog.search(‘12abc’).group() # 通过调用group()方法得到匹配的字符串,如果字符串没有匹配,则返回None。
‘12’
》》prog.match(‘123abc’)
<_sre.SRE_Match object; span=(0, 2), match=‘12’>
》》prog.match(‘123abc’).group()
‘12’2、re.search(pattern,string,flags = 0 )
扫描字符串以查找正则表达式模式产生匹配项的第一个位置 ,然后返回相应的match对象。None如果字符串中没有位置与模式匹配,则返回;否则返回false。请注意,这与在字符串中的某个点找到零长度匹配不同。#在这个字符串进行匹配,只会匹配一个对象
》》re.search(‘\w+’,‘abcde’).group()
‘abcde’
》》re.search(‘a’,‘abcde’).group()
‘a’3、re.match(pattern,string,flags = 0 )
如果字符串开头的零个或多个字符与正则表达式模式匹配,则返回相应的匹配对象。None如果字符串与模式不匹配,则返回;否则返回false。请注意,这与零长度匹配不同。*#同search,不过在字符串开始处进行匹配,只会匹配一个对象 *
》》re.match(‘a’,‘abcade’).group()
‘a’
》》re.match(‘\w+’,‘abc123de’).group()
‘abc123de’
》》re.match(‘\D+’,‘abc123de’).group() #非数字
‘abc’4、re.fullmatch(pattern,string,flags = 0 )
如果整个字符串与正则表达式模式匹配,则返回相应的match对象。None如果字符串与模式不匹配,则返回;否则返回false。请注意,这与零长度匹配不同。》》re.fullmatch(‘\w+’,‘abcade’).group()
‘abcade’
》》re.fullmatch(‘abcade’,‘abcade’).group()
‘abcade’5、re.split(pattern,string,maxsplit = 0,flags = 0 )
通过出现模式来拆分字符串。如果在pattern中使用了捕获括号,那么模式中所有组的文本也将作为结果列表的一部分返回。如果maxsplit不为零,则最多会发生maxsplit分割,并将字符串的其余部分作为列表的最后一个元素返回。》》re.split(‘[ab]’, ‘abcd’) # 先按’a’分割得到’‘和’bcd’,在对’‘和’bcd’分别按’b’分割
[’‘, ‘’, ‘cd’]
》》re.split(r’\W+‘, ‘Words, words, words.’)
[‘Words’, ‘words’, ‘words’, ‘’]
》》re.split(r’(\W+)‘, ‘Words, words, words.’)
[‘Words’, ‘, ‘, ‘words’, ‘, ‘, ‘words’, ‘.’, ‘’]
》》re.split(r’\W+’, ‘Words, words, words.’, 1)
[‘Words’, ‘words, words.’]
》》re.split(’[a-f]+’, ‘0a3B9’, flags=re.IGNORECASE)
[‘0’, ‘3’, ‘9’]
如果分隔符中有捕获组,并且该匹配组在字符串的开头匹配,则结果将从空字符串开始。字符串的末尾也是如此:
》》re.split(r’(\W+)‘, ‘…words, words…’)
[’', ‘…’, ‘words’, ', ', ‘words’, ‘…’, ‘’]6、re.findall(pattern,string,flags = 0 )
以string列表形式返回string中pattern的所有非重叠匹配项。从左到右扫描该字符串,并以找到的顺序返回匹配项。如果该模式中存在一个或多个组,则返回一个组列表;否则,返回一个列表。如果模式包含多个组,则这将是一个元组列表。空匹配项包含在结果中。》》 re.findall(‘a’, ‘This is a beautiful place!’)
[‘a’, ‘a’, ‘a’]7、re.finditer(pattern,string,flags = 0 )
返回一个迭代器,该迭代器在string类型的RE 模式的所有非重叠匹配中产生匹配对象。 从左到右扫描该字符串,并以找到的顺序返回匹配项。空匹配项包含在结果中。》》re.finditer(‘[ab]’, ‘This is a beautiful place!’)
<callable_iterator object at 0x0000000000DCDA90> #迭代器对象
》》 ret=re.finditer(‘[ab]’, ‘This is a beautiful place!’)
》》 next(ret).group() #查看下一个匹配值
‘a’
》》 [i.group() for i in ret] #查看剩下所有匹配的值
[‘b’, ‘a’, ‘a’]8、re.sub(pattern,repl,string,count = 0,flags = 0 )
返回通过用替换repl替换字符串中最左边的不重叠模式所获得的字符串。如果找不到该模式, 则返回的字符串不变。 repl可以是字符串或函数;如果是字符串,则处理其中的任何反斜杠转义。即,将其转换为单个换行符,将其转换为回车,依此类推。count参数表示将匹配到的内容进行替换的次数》》 re.sub(‘\d’, ‘S’, ‘abc12jh45li78’, 2) #将匹配到的数字替换成S,替换2个
‘abcSSjh45li78’
》》 re.sub(‘\d’, ‘S’, ‘abc12jh45li78’) #将匹配到所有的数字替换成S
‘abcSSjhSSliSS’9、re.subn(pattern,repl,string,count = 0,flags = 0 )
执行与相同的操作sub(),但返回一个元组。(new_string, number_of_subs_made)》》 re.subn(‘\d’, ‘S’, ‘abc12jh45li78’, 3)
(‘abcSSjhS5li78’, 3)10、re.escape(pattern)
escape中的所有字符图案,除了ASCII字母,数字和 ‘_’。如果要匹配可能包含正则表达式元字符的任意文字字符串,这将很有用。》》 re.escape(‘python.exe\n’)
‘python\.exe\\n’11、search()与match()方法
Python提供了两种基于正则表达式的原始操作: re.match()仅在字符串的开头匹配,re.search()检查匹配项,在字符串中的任何位置检查匹配项(这是Perl的默认设置)。》》 re.match(“c”, “abcdef”) #Not match
》》 re.search(“c”, “abcdef”) #match
<_sre.SRE_Match object; span=(2, 3), match=‘c’>以开头的正则表达式’^'可用于search()限制字符串开头的匹配项:
re.match(“c”, “abcdef”) #Not match
re.search(“^c”, “abcdef”) #Not match
re.search(“^a”, “abcdef”) #match
<_sre.SRE_Match object; span=(0, 1), match=‘a’>
(三)正则表达式基本符号:
^ 表示匹配字符串的开始位置 (例外 用在中括号中[ ] 时,可以理解为取反,表示不匹配括号中字符串)
$ 表示匹配字符串的结束位置
表示匹配 零次到多次
+表示匹配 一次到多次 (至少有一次)
? 表示匹配零次或一次
. 表示匹配单个字符
| 表示为或者,两项中取一项
( ) 小括号表示匹配括号中全部字符
[ ] 中括号表示匹配括号中一个字符 范围描述 如[0-9 a-z A-Z]
{ } 大括号用于限定匹配次数 如 {n}表示匹配n个字符 {n,}表示至少匹配n个字符 {n,m}表示至少n,最多m
\ 转义字符 如上基本符号匹配都需要转义字符 如 * 表示匹配号
\w 表示英文字母和数字 \W 非字母和数字
\d 表示数字 \D 非数字
常用的正则表达式:
匹配中文字符的正则表达式: [\u4e00-\u9fa5]
匹配双字节字符(包括汉字在内):[^\x00-\xff]
匹配空行的正则表达式:\n[\s| ]\r
匹配HTML标记的正则表达式:/<(.)>.</\1>|<(.) />/
匹配首尾空格的正则表达式:(^\s*)|(\s*$)
匹配IP地址的正则表达式:/(\d+).(\d+).(\d+).(\d+)/g //
匹配Email地址的正则表达式:\w+([-+.]\w+)@\w+([-.]\w+).\w+([-.]\w+)*
匹配网址URL的正则表达式:http://(/[\w-]+.)+[\w-]+(/[\w- ./?%&=]*)?
(好多打出来成了乱码,我用文档截图出来了o(╥﹏╥)o)
10 - 深拷贝和浅拷贝
- 直接赋值:其实就是对象的引用(别名)。
- 浅拷贝(copy):拷贝父对象,不会拷贝对象的内部的子对象。
- 深拷贝(deepcopy):
copy 模块的 deepcopy 方法,完全拷贝了父对象及其子对象。
(一)字典浅拷贝实例
a = {1: [1,2,3]}
b = a.copy()
print(a, b) # ({1: [1, 2, 3]}, {1: [1, 2, 3]})
a[1].append(4)
print(a, b) # ({1: [1, 2, 3, 4]}, {1: [1, 2, 3, 4]})
(二)深度拷贝需要引入 copy 模块:
import copy
c = copy.deepcopy(a)
print(a, c) # ({1: [1, 2, 3, 4]}, {1: [1, 2, 3, 4]})
a[1].append(5)
print(a,c) # ({1: [1, 2, 3, 4, 5]}, {1: [1, 2, 3, 4]})
(三)更多实例
以下实例是使用 copy 模块的 copy.copy( 浅拷贝 )和(copy.deepcopy ):
import copy
a = [1, 2, 3, 4, ['a', 'b']] #原始对象
b = a #赋值,传对象的引用
c = copy.copy(a) #对象拷贝,浅拷贝
d = copy.deepcopy(a) #对象拷贝,深拷贝
a.append(5) #修改对象a
a[4].append('c') #修改对象a中的['a', 'b']数组对象
print( 'a = ', a )
print( 'b = ', b )
print( 'c = ', c )
print( 'd = ', d )
以上实例执行输出结果为:
('a = ', [1, 2, 3, 4, ['a', 'b', 'c'], 5])
('b = ', [1, 2, 3, 4, ['a', 'b', 'c'], 5])
('c = ', [1, 2, 3, 4, ['a', 'b', 'c']])
('d = ', [1, 2, 3, 4, ['a', 'b']])
11 - 不同数据类型及其特点
- Python中的基本数据类型:数字(number)、字符串(String)、布尔值(boolean)、列表(list)、元组(tuple)、字典(dict)、集合(set)
- 数字:就是数学中的数字,常见的可以分为整数(int)和浮点数(float),【complex(复数)了解即可,不做要求】。可以做数学中的四则运算,浮点中理解为数学中的小数
- 字符串:相当于中文中的汉字,英文中的单词,它可以包含:中文汉字、英文字母、数字、符号等,是属于文字范畴的,字符串应该用单引号或者双引号包裹
【int 长整形】
int为整数,使用int可以将小数或者整数形式的字符转换成整数
不能转换小数形式的字符(会报错)
【float 浮点型】
float为浮点型(简单理解为小数),使用float可以将整数转换成小数
可以直接转换小数形式的字符
【string 字符类型】
在python变量定义中,如果其赋值的内容是通过单引号或双引号引起来的内容就是字符串str类型。
字符串的操作见知识点13
【boolean 布尔类型】
布尔类型是与逻辑相关一种数据类型,只有两个值:True(真)与False(假)
其中布尔类型值可以相加,但一旦相加,类型就会转换为int类型
布尔类型的运算,详情见知识点2
【list 列表】
python的列表可以完成大多数集合类的数据结构实现。它支持字符,数字,字符串甚至可以包含列表(即嵌套或者叫多维列表,可以用来表示多维数组)。
列表的增删改查:
1.增
此时我们用到一个函数append(),其作用是:
在列表的末尾增加一个指定的元素,比如说:
n = [1,2,3,4,5,6,7,8,9,10]
n.append(11)//其中11为指定的元素,增加到列表的末尾
此外,还有一个函数也有该功能,那就是extend(),但是这个函数有所限制:
extend()方法的参数必须是一个可迭代对象,新的内容是追加到原列表最后一个元素的后面。
2.删
如果我们要删除列表里面的某一个元素,那么此时我们可以用到remove()函数,其作用是删除一个指定的元素!
如: List.remove(“A”)
即是将元素"A"删除
3.改
如果外面想要修改列表里面的元素,即将列表里面的元素替换,可以使用下标索引的方法!
如: List[1]=“A”
即是将索引为1的元素改成字符A
4.查
在index()函数中输入元素,可以获取到下标索引值!
如:
List = [“A”,“B”,“C”,“A”]
print(List.index(“A”))
因为列表中第一个A是第一个元素(索引为0),所以List.index(“A”)=0index(x,star,end)函数,顾名思义x表示在列表查找的元素,star表示开始查找的下标索引值的位置,end表示结束查找的下标索引值的位置。
【tuple 元组】
python的元组类似于list列表,元组用 () 标识。内部元素用逗号隔开。但是元组不能二次赋值,相当于只读列表。虽然tuple的元素不可改变,但它可以包含可变的对象(上述可变数据),比如list列表。
它支持字符,数字,字符串,列表,元组等所有类型
元组的取值、截取、连接、重复与列表一样
【dict 字典】
字典(dictionary)是除列表以外python之中最灵活的内置数据结构类型;列表是有序的对象集合,字典是无序的对象集合;字典用"{ }"标识;字典由索引(key)和它对应的值value组成
字典取值,字典当中的元素是通过键来存取的,而不是通过偏移存取
键(key)必须使用不可变类型(数字、布尔、字符串、元组)
在同一个字典中,键(key)必须是唯一的
【set 集合】
集合(set)是由一个或数个形态各异的大小整体组成的,构成集合的事物或对象称作元素或是成员
基本功能是进行成员关系测试和删除重复元素
可以使用大括号 { } 或者 set() 函数创建集合
注意:创建一个空集合必须用 set() 而不是 { },因为 { } 是用来创建一个空字典
不能往集合里边添加可变数据类型的数据
a与b(a&b)表示集合a和集合b都包含的元素;
a非b(a-b)表示集合a中包含但是集合b中不包含的元素;
a异或b(a^b),表示集合a和集合b不同时包含的所有元素;
a或b(a|b),表示集合a和集合b都包含的所有的元素。
集合不能通过索引值进行查询!
一些常用的集合方法:
- clear()方法可以清空集合里面的元素
- add()方法可以为集合添加元素
- remove()方法可以删除集合里面存在的元素(但是删除集合中不存在的元素会报错)
- discard()方法可以删除集合里存在的元素(删除集合中不存在的元素也不会报错)
- pop()方法可以随机删除元素
不同类型转换
12 - 排序函数(主要考察序列排序)
以下以列表 List = [1,2,6,9,3,5,77,3,56] 为例
1.sorted(list,reverse=True)
在排序后会生成一个新的序列,不改变原有序列
2.sort()
排序后改变原有序列,不生成新的序列
3.sort()和sorted()的区别:
(1):sort()排序改变原有序列,而sorted()排序生成一个新的序列,不改变原有的序列
(2):两个调用不一样,sort()调用:序列.sort()
sorted()调用:sorted(序列,reverse=True/False)
13 - 字符串的操作方式
1.字符串索引
a[i] 代表字符串a 第i+1个位置的索引,a[-1]代表字符串a最后一个位置的索引
2.字符串截取
s=a[i:j],其中i,j可以不写,表示从位置i开始到位置j结束,其中截取的字符串不包括位置j。
效果类似于列表的切片,详情见知识点7
3.字符串拼接:“+”
拼接(+)类似于一个胶水,会把两个字符黏在一起
4.字符串复用:“*“
复用(*)可以简单理解为是将字符重复n次
14 - 递归
(递归这一部分参考了某个文献,但是时间太久了,忘记是哪个文档了!!有看到的小伙伴评论提醒我一下,我好标注一下原作者!!)
>什么是递归
在计算机中,程序调用自身的编程技巧我们称之为递归算法。那么再通俗一点来讲就是:在某个python文件中,有一个函数,这个函数可以在自己的函数体内根据条件,自己调用自己的函数,那么这样自身调用自身的过程或者说行为,我们称之为递归。
>为什么要使用递归
(1)如果不使用递归,而使用循环,那么代码量会比较多
(2)使用循环实现的那么程序不容易理解,但是使用递归就会好理解很对
(3)如果使用循环,程序的性能可能更高,如果使用递归,程序更容易理解,所以如何选择什么对你来说更重要
>递归的特征
(1)要实现递归必须有一个函数
(2)并且在这个函数体内要自己调用自己
(3)递归必须要有一个深度,也就是判断条件,这个判断条件是判断次数或者说个数的
(4)到达一定的深度后必须返回一个东西,哪怕是空的也可以,目的是结束递归
(5)未到达一定深度时,可以返回该函数,但同时也可以不返回,这个根据需求而定,但是必须不断调用函数自身。
>递归的典型例题:求解斐波那契数
15 - 动态规划
(同看的大佬的!大家找到原创告诉我!感恩!)
>什么是动态规划
动态规划(英语:Dynamic programming,简称 DP),是一种在数学、管理科学、计算机科学、经济学和生物信息学中使用的,通过把原问题分解为相对简单的子问题的方式求解复杂问题的方法。动态规划常常适用于有重叠子问题和最优子结构性质的问题。
简单来说,动态规划其实就是,给定一个问题,我们把它拆成一个个子问题,直到子问题可以直接解决。然后呢,把子问题答案保存起来,以减少重复计算。再根据子问题答案反推,得出原问题解的一种方法。(一般这些子问题很相似,可以通过函数关系式递推出来。然后呢,动态规划就致力于解决每个子问题一次,减少重复计算,比如斐波那契数列就可以看做入门级的经典动态规划问题)
>动态规划的核心思想
动态规划最核心的思想,就在于拆分子问题,记住过往,减少重复计算
一个简单的动态规划的例子
>规划分类和代表性问题
线性动规:拦截导弹,合唱队形,挖地雷,建学校,剑客决斗等;
区域动规:石子合并,加分二叉树,统计单词个数,炮兵布阵等;
树形动规:贪吃的九头龙,二分查找书,聚会的欢乐,数字三角形等;
背包问题:01背包问题,完全背包问题,分组背包问题,二维背包,装箱问题,挤牛奶等;
应用实例:最短路径问题,项目管理,网络流优化等。
一个例子带你走进动态规划 – 青蛙跳阶问题(这里借鉴了一下腾讯云一个大佬的写的文章!)
暴力递归leetcode原题:一只青蛙一次可以跳上1级台阶,也可以跳上2级台阶。求该青蛙跳上一个 10 级的台阶总共有多少种跳法。
有些小伙伴第一次见这个题的时候,可能会有点蒙圈,不知道怎么解决。其实可以试想:
- 要想跳到第10级台阶,要么是先跳到第9级,然后再跳1级台阶上去;要么是先跳到第8级,然后一次迈2级台阶上去。
- 同理,要想跳到第9级台阶,要么是先跳到第8级,然后再跳1级台阶上去;要么是先跳到第7级,然后一次迈2级台阶上去。
- 要想跳到第8级台阶,要么是先跳到第7级,然后再跳1级台阶上去;要么是先跳到第6级,然后一次迈2级台阶上去。
假设跳到第n级台阶的跳数我们定义为f(n),很显然就可以得出以下公式:
那f(2) 或者 f(1) 等于多少呢?
- 当只有2级台阶时,有两种跳法,第一种是直接跳两级,第二种是先跳一级,然后再跳一级。即f(2) = 2;
- 当只有1级台阶时,只有一种跳法,即f(1)= 1;
因此可以用递归去解决这个问题:
画一个递归树
- 要计算原问题 f(10),就需要先计算出子问题 f(9) 和 f(8)
- 然后要计算 f(9),又要先算出子问题 f(8) 和f(7),以此类推。
- 一直到 f(2) 和 f(1),递归树才终止。
我们先来看看这个递归的时间复杂度吧:
递归时间复杂度 = 解决一个子问题时间*子问题个数
- 一个子问题时间 = f(n-1)+f(n-2),也就是一个加法的操作,所以复杂度是 O(1);
- 问题个数 =
递归树节点的总数,递归树的总节点 = 2n-1,所以是复杂度O(2n)。 因此,青蛙跳阶,递归解法的时间复杂度 = O(1) *
O(2^n) = O(2^n),就是指数级别的,爆炸增长的,如果n比较大的话,超时很正常的了。
回过头来,你仔细观察这颗递归树,你会发现存在大量重复计算,比如f(8)被计算了两次, f(7)被重复计算了3次…所以这个递归算法低效的原因,就是存在大量的重复计算!
既然存在大量重复计算,那么我们可以先把计算好的答案存下来,即造一个备忘录,等到下次需要的话,先去备忘录查一下,如果有,就直接取就好了,备忘录没有才开始计算,那就可以省去重新重复计算的耗时啦!这就是带备忘录的解法。
>带备忘录的递归解法(自顶向下)
一般使用一个数组或者一个哈希map充当这个备忘录。
第一步,f(10)= f(9) + f(8),f(9) 和f(8)都需要计算出来,然后再加到备忘录中,如下:
第二步, f(9) = f(8)+ f(7),f(8)= f(7)+ f(6), 因为 f(8) 已经在备忘录中啦,所以可以省掉,f(7),f(6)都需要计算出来,加到备忘录中~
第三步, f(8) = f(7)+ f(6),发现f(8),f(7),f(6)全部都在备忘录上了,所以都可以剪掉。
所以呢,用了备忘录递归算法,递归树变成光秃秃的树干咯,如下:
带备忘录的递归算法,子问题个数=树节点数=n,解决一个子问题还是O(1),所以带备忘录的递归算法的时间复杂度是O(n)。接下来呢,我们用带备忘录的递归算法去撸代码,解决这个青蛙跳阶问题的超时问题咯~,代码如下:
其实,还可以用动态规划解决这道题。
>自底向上的动态规划
动态规划跟带备忘录的递归解法基本思想是一致的,都是减少重复计算,时间复杂度也都是差不多。但是呢:
- 带备忘录的递归,是从f(10)往f(1)方向延伸求解的,所以也称为自顶向下的解法。
- 动态规划从较小问题的解,由交叠性质,逐步决策出较大问题的解,它是从f(1)往f(10)方向,往上推求解,所以称为自底向上的解法。
动态规划有几个典型特征,最优子结构、状态转移方程、边界、重叠子问题。在青蛙跳阶问题中:
- f(n-1)和f(n-2) 称为 f(n)的最优子结构
- f(n)= f(n-1)+f(n-2)就称为状态转移方程
- f(1) =1, f(2) = 2 就是边界啦
- 比如f(10)= f(9)+f(8),f(9) = f(8) + f(7),f(8)就是重叠子问题。
我们来看下自底向上的解法,从f(1)往f(10)方向,想想是不是直接一个for循环就可以解决啦,
如下:
带备忘录的递归解法,空间复杂度是O(n),但是呢,仔细观察上图,可以发现,f(n)只依赖前面两个数,所以只需要两个变量a和b来存储,就可以满足需求了,因此空间复杂度是O(1)就可以啦
动态规划实现代码如下:
>动态规划的解题套路
什么样的问题可以考虑使用动态规划解决呢?
如果一个问题,可以把所有可能的答案穷举出来,并且穷举出来后,发现存在重叠子问题,就可以考虑使用动态规划。
比如一些求最值的场景,如最长递增子序列、最小编辑距离、背包问题、凑零钱问题等等,都是动态规划的经典应用场景。
>动态规划的解题思路
动态规划的核心思想就是拆分子问题,记住过往,减少重复计算。 并且动态规划一般都是自底向上的,因此到这里,基于青蛙跳阶问题,我总结了一下我做动态规划的思路:
- 穷举分析
- 确定边界
- 找出规律,确定最优子结构
- 写出状态转移方程
>1.穷举分析
- 当台阶数是1的时候,有一种跳法,f(1) =1
- 当只有2级台阶时,有两种跳法,第一种是直接跳两级,第二种是先跳一级,然后再跳一级。即f(2) = 2;
- 当台阶是3级时,想跳到第3级台阶,要么是先跳到第2级,然后再跳1级台阶上去,要么是先跳到第 1级,然后一次迈 2 级台阶上去。所以f(3)= f(2) + f(1) =3
- 当台阶是4级时,想跳到第3级台阶,要么是先跳到第3级,然后再跳1级台阶上去,要么是先跳到第 2级,然后一次迈 2 级台阶上去。所以f(4) = f(3) + f(2) =5
- 当台阶是5级时…
>2.确定边界
通过穷举分析,我们发现,当台阶数是1的时候或者2的时候,可以明确知道青蛙跳法。f(1) =1,f(2) = 2,当台阶n>=3时,已经呈现出规律f(3) = f(2) + f(1) =3,因此f(1) =1,f(2) = 2就是青蛙跳阶的边界。
>3. 找规律,确定最优子结构
n>=3时,已经呈现出规律 f(n) = f(n-1) + f(n-2) ,因此,f(n-1)和f(n-2) 称为 f(n) 的最优子结构。什么是最优子结构?有这么一个解释:
一道动态规划问题,其实就是一个递推问题。假设当前决策结果是f(n),则最优子结构就是要让 f(n-k) 最优,最优子结构性质就是能让转移到n的状态是最优的,并且与后面的决策没有关系,即让后面的决策安心地使用前面的局部最优解的一种性质
>4.写出状态转移方程
通过前面3步,穷举分析,确定边界,最优子结构,我们就可以得出状态转移方程啦:
>5. 代码实现
我们实现代码的时候,一般注意从底往上遍历哈,然后关注下边界情况,空间复杂度,也就差不多啦。动态规划有个框架的,大家实现的时候,可以考虑适当参考一下:
16 - 面向对象主要有四大特性
1、抽象
忽略一个主题中与当前目标无关的东西,专注的注意与当前目标有关的方面。(就是把现实世界中的某一类东西,提取出来,用程序代码表示,抽象出来的一般叫做类或者接口)。抽象并不打算了解全部问题,而是选择其中的一部分,暂时不用部分细节。抽象包括两个方面,一个数据抽象,而是过程抽象。
数据抽象 -->表示世界中一类事物的特征,就是对象的属性。比如鸟有翅膀,羽毛等(类的属性)
过程抽象 -->表示世界中一类事物的行为,就是对象的行为。比如鸟会飞,会叫(类的方法)
2、封装
封装是面向对象的特征之一,是对象和类概念的主要特性。封装就是把过程和数据包围起来,对数据的访问只能通过已定义的界面。如私有变量,用set,get方法获取。
封装保证了模块具有较好的独立性,使得程序维护修改较为容易。对应用程序的修改仅限于类的内部,因而可以将应用程序修改带来的影响减少到最低限度。
3、继承
一种联结类的层次模型,并且允许和鼓励类的重用,提供一种明确表达共性的方法。对象的一个新类可以从现有的类中派生,这个过程称为类继承。新类继承了原始类的特性,新类称为原始类的派生类(子类),原始类称为新类的基类(父类)。派生类可以从它的父类哪里继承方法和实例变量,并且类可以修改或增加新的方法使之更适合特殊的需要。因此可以说,继承为了重用父类代码,同时为实现多态性作准备。
4、多态
多态是指允许不同类的对象对同一消息做出响应。多态性包括参数化多态性和包含多态性。多态性语言具有灵活/抽象/行为共享/代码共享的优势,很好的解决了应用程序函数同名问题。总的来说,方法的重写,重载与动态链接构成多态性。java引入多态的概念原因之一就是弥补类的单继承带来的功能不足。
动态链接 -->对于父类中定义的方法,如果子类中重写了该方法,那么父类类型的引用将调用子类中的这个方法,这就是动态链接。
>常见报错以及基本解决方法
(欢迎大家留言不同的报错!一起琢磨钻研,然后我追加上去~~)
1 - PermissionError
一般是允许命令出错,重新保存即可,如果这个程序有打开一些文件(如图片、PDF),则需要先关闭之前程序打开的文件,再运行
2 - FileNotFoundError
文件无法找到,出现这种情况,一定要检查一下路径,比如我们要是用xx.jpg这张图,就需要检查一下,代码和这张图是否保存在一起!
3 - SyntaxError 之 invalid syntax
无效的语法句法,这个90%会是符号问题,检查一下有没有符号遗漏(特别是逗号分割、括号成对、循环或者 if判断的冒号,很容易写漏了),剩下的就要检查一下是不是有其他的语法问题,比如 拼写错了
4 - AttributeError
属性问题,一般属性出现问题,就要看看我们有没有定义该种属性,或者我们用到方法是不是对的。当然像这种有【NoneType】的字样,就要检查一下有没有对应的素材(比如图片),重点检查路径
5 - OSError
资源问题,检查资源和代码保存的路径是怎么样的,看看代码能否读取到资源(如字体)
6 - NameError
直译过来是名字有问题,一般都是拼写错误,主要检查之前怎么定义,以及后面怎么使用的
7 - AssertionError
出现这种情况大多就是参数问题,特别是我们在制图是,x、y轴的数据需要一一对应(也就是数量是相等的,x里有多少个数据,y里就有多少个),数量不一致,就会有这种问题
8 - No such file or directory
这个问题的解决方法很简单,因为一旦没保存好,或者找不到文件,都会出这个问题,但是因为没有报具体的找不到什么,一般都是没保存好,重新保存再运行就OK
9 - SyntaxError 之 position argument follows keyword argument
keyword argument就是关键字参数,出现这种情况就是咱们关键字错了,着重检查关键字有没有拼写错误
10 - IndexError
index就是索引,out of range表示超过范围,所以这个报错我们可以简单理解为,索引超过范围报错!索引值是0~n-1的,所以要检查索引!
11 - TypeError
类型错误,着重检查类型,如我们要使用字符,代码中的数据却是数值
12 - UnboundLocalError
代码中有参数在定义前就调用了,看看能否前置定义或者使用global定型全局变量设置
13 - UnicodeDecodeError
编码格式问题,最常用的及时gbk和utf-8的类型,一般设置encoding会二者选其一,根据自己电脑的编码调整
14 - KeyError
如果用到了字典,那么就是键的问题,一般都是键前后命名不一致。
若没有用到字典,则有可能是关键词的错误,检查对应关键词是否拼写正确(特别是大小写)
>其他好物
(到处收集的好东西~欢迎大家评论分享!)
● 一个傻瓜式构建可视化 web的 Python 神器 – streamlit
● 一行代码将Python程序转换为图形界面应用
● 如何在 Win上写 Python 代码?最佳攻略来袭!
● pyside2官方文档
● pyecharts老版本官网
● QT Creator安装网址
● 640页超全Python基础教程
python基础教程链接 提取码:bhpa
● 《点燃我,温暖你》中的跳动爱心代码
#晚上星月争辉,美梦陪你入睡
import random
from math import sin, cos, pi, log
from tkinter import *
CANVAS_WIDTH= 640 #画布的宽
CANVAS_HEIGHT = 480 #画布的高
CANVAS_CENTER_X= CANVAS_WIDTH/ 2 #画布中心的X轴坐标
CANVAS_CENTER_Y = CANVAS_HEIGHT / 2 #画布中心的Y轴坐标
IMAGE_ENLARGE= 11 #放大比例
HEART_COLOR = "#FF99CC" #心的颜色,这个是中国红
def heart_function(t,shrink_ratio: float = IMAGE_ENLARGE):
'''
”爱心函数生成器”
:param shrink_ ratio: 放大比例
:paramt:参数
:return:坐标
'''
#基础函数
x= 16* (sin(t) ** 3)
y= -(13* cos(t)- 5* cos(2*t)-2*cos(3 *t)- cos(4*t))
#放大
x *= shrink_ratio
y *= shrink_ratio
#移到画布中央
x += CANVAS_CENTER_X
y += CANVAS_CENTER_Y
return int(x), int(y)
def scatter_inside(x, y, beta=0.15):
'''
随机内部扩散
:param X:原x
:paramy:原y
:param beta:强度
:return:新坐标
'''
ratio_x= -beta * log(random.random())
ratio_y= -beta * log(random.random())
dx= ratio_x* (x- CANVAS_CENTER_X)
dy= ratio_y* (y- CANVAS_CENTER_Y)
return x-dx,y-dy
def shrink(x, y, ratio):
'''
抖动
:paramx:原x
:paramy:原y
:param ratio:比例
:return:新坐标
'''
force= -1/ (((x - CANVAS_CENTER_X)**2 + (y - CANVAS_CENTER_Y)**2)**0.6) #这个参数...
dx= ratio * force * (x - CANVAS_CENTER_X)
dy = ratio * force * (y- CANVAS_CENTER_Y)
return x-dx, y - dy
def curve(p):
'''
自定义曲线函数,调整跳动周期
:paramp:参数
:return:正弦
'''
# 可以尝试换其他的动态函数,达到更有力量的效果(贝塞尔? )
return 2*(2* sin(4*p))/(2*pi)
class Heart:
'''
爱心类
'''
def __init__(self, generate_frame=20):
self._points= set() #原始爱心坐标集合
self._edge_diffusion_points = set() #边缘扩散效果点坐标集合
self._center_diffusion_points = set() #中心扩散效果点坐标集合
self.all_points= {} #每帧动态点坐标
self.build(2000)
self.random_halo = 1000
self.generate_frame = generate_frame
for frame in range(generate_frame):
self.calc(frame)
def build(self, number):
# 爱心
for _ in range(number):
t = random.uniform(0, 2 * pi) # 随机不到的地方造成爱心有缺口
x, y = heart_function(t)
self._points.add((x, y))
# 爱心内扩散
for _x, _y in list(self._points):
for _ in range(3):
x, y = scatter_inside(_x, _y, 0.05)
self._edge_diffusion_points.add((x, y))
# 爱心内再次扩散
point_list = list(self._points)
for _ in range(4000):
x, y = random.choice(point_list)
x, y = scatter_inside(x, y, 0.17)
self._center_diffusion_points.add((x, y))
@staticmethod
def calc_position(x , y, ratio):
# 调整缩放比例
force = 1 / (((x - CANVAS_CENTER_X) ** 2 + (y - CANVAS_CENTER_Y) ** 2) ** 0.520) # 魔法参数
dx = ratio * force * (x - CANVAS_CENTER_X) + random.randint(-1, 1)
dy = ratio * force * (y - CANVAS_CENTER_Y) + random.randint(-1, 1)
return x - dx, y - dy
def calc(self, generate_frame):
ratio = 10 * curve(generate_frame / 10 * pi) # 圆滑的周期的缩放比例
halo_radius = int(4 + 6 * (1 + curve(generate_frame / 10 * pi)))
halo_number = int(3000 + 4000 * abs(curve(generate_frame / 10 * pi) ** 2))
all_points = []
# 光环
heart_halo_point = set() # 光环的点坐标集合
for _ in range(halo_number):
t = random.uniform(0, 2 * pi) # 随机不到的地方造成爱心有缺口
x, y = heart_function(t, shrink_ratio = 11.6) # 魔法参数
x, y = shrink(x, y, halo_radius)
if (x, y) not in heart_halo_point:
# 处理新的点
heart_halo_point.add((x, y))
x += random.randint(-14, 14)
y += random.randint(-14, 14)
size = random.choice((1, 2, 2))
all_points.append((x, y, size))
# 轮廓
for x, y in self._points:
x, y = self.calc_position(x, y, ratio)
size = random.randint(1, 3)
all_points.append((x, y, size))
# 内容
for x, y in self._edge_diffusion_points:
x, y = self.calc_position(x, y, ratio)
size = random.randint(1, 2)
all_points.append((x, y, size))
for x, y in self._center_diffusion_points:
x, y = self.calc_position(x, y, ratio)
size = random.randint(1, 2)
all_points.append((x, y, size))
self.all_points[generate_frame] = all_points
def render(self, render_canvas, render_frame):
for x, y, size in self.all_points[render_frame % self.generate_frame]:
render_canvas.create_rectangle(x, y, x + size, y + size, width=0, fill=HEART_COLOR)
def draw(main: Tk, render_canvas: Canvas, render_heart: Heart, render_frame = 0):
render_canvas.delete('all')
render_heart.render(render_canvas, render_frame)
main.after(200, draw, main, render_canvas, render_heart, render_frame + 1)
if __name__ == '__main__':
root = Tk() # 一个Tk
canvas = Canvas(root, bg='black', height=CANVAS_HEIGHT, width = CANVAS_WIDTH)
canvas.pack()
heart = Heart() # 心
draw(root, canvas, heart) # 开始画画~
root.mainloop()
● 泊松分布
# 泊松分布随机数的生成方法
import math
import matplotlib.pyplot as plt
def PoissonDistribution(avg, k):
return (avg**(k)) * (math.exp(-avg)) / math.factorial(k)
def cumsum(a):
cumsum = []
for i in range(0, len(a)):
tmp = 0.0
for j in range(0, i):
tmp += a[j]
cumsum.append(tmp)
return cumsum
if __name__ == '__main__':
poss = [PoissonDistribution(10, i) for i in range(1, 50)]
cumsumPoss = cumsum(poss)
plt.bar(range(1, 50), poss)
plt.plot(range(1, 50), cumsumPoss)
plt.show()
● 【0基础学爬虫】爬虫基础之自动化工具 Selenium 的使用
● 太极库(Taichi)
超级好用!(下一条是“使用说明”)
太极库!
● 关于 Taichi,你最想搞懂的问题都在这了!
● 自从学了这个模块,我基本告别了print
● python屏幕取色器(记得更改屏幕大小)
import os
from time import sleep
import tkinter
import tkinter.filedialog
import tkinter.messagebox
from PIL import ImageGrab, Image
root = tkinter.Tk()
root.geometry('100x40+400+300')
root.resizable(False, False)
class MyCapture:
def __init__(self, png):
# 变量X和Y用来记录鼠标左键按下的位置
self.X = tkinter.IntVar(value=0)
self.Y = tkinter.IntVar(value=0)
# 获取屏幕尺寸
screenWidth = root.winfo_screenwidth()
screenHeight = root.winfo_screenheight()
# 创建顶级组件容器,与屏幕尺寸一样大
self.top = tkinter.Toplevel(
root, width=screenWidth, height=screenHeight)
# 不显示最大化、最小化按钮
self.top.overrideredirect(True)
self.image = tkinter.PhotoImage(file=png)
# 创建画布
self.canvas = tkinter.Canvas(
self.top, bg='white', width=screenWidth, height=screenHeight)
# 显示全屏截图,在全屏截图上进行区域截图
self.canvas.create_image(
screenWidth//2, screenHeight//2, image=self.image)
# 获取鼠标左键抬起的位置,取色
def onLeftButtonUp(event):
im = Image.open(png)
color = im.getpixel((event.x, event.y))[:3]
color = map(lambda x: hex(x)[2:], color)
color = map(lambda x: x if len(x) == 2 else '0'+x, color)
color = '#' + ''.join(color)
tkinter.messagebox.showinfo('', str(color))
# 关闭当前窗口
self.top.destroy()
self.canvas.bind('<ButtonRelease-1>', onLeftButtonUp)
self.canvas.pack(fill=tkinter.BOTH, expand=tkinter.YES)
# 开始截图
def buttonCaptureClick():
# 最小化主窗口
root.state('icon')
sleep(0.2)
filename = 'temp.png'
im = ImageGrab.grab()
im.save(filename)
im.close()
# 显示全屏幕截图
w = MyCapture(filename)
buttonCapture.wait_window(w.top)
# 截图结束,恢复主窗口,并删除临时的全屏幕截图文件
root.state('normal')
os.remove(filename)
buttonCapture = tkinter.Button(root, text='取色', command=buttonCaptureClick)
buttonCapture.place(x=10, y=10, width=80, height=20)
#启动消息主循环
root.mainloop()