python前端基础知识总结
知识总结
认识Python
安装环境
第一个程序
变量定义
什么是变量?
标识符命名规范
命名原则
示例:
# 单一赋值
a = 10
# 统一赋值
b = c = d = 20
# 对称赋值
e, f = 30, 40
# 删除变量
del a
# 此处会报NameError错
print(a)
使用常量
代码注释
输入输出
输出:将特定的内容打印出来
a = 10
b = 20
# 输出:可以一次打印多个数据
# sep:多个数据的分割内容
# end:结束时的内容,默认是'\n',表示换行
print(a, b, sep=',', end='')
输入:程序运行后,等待用户的输入,然后才能进行下一步的操作
# 获取用户输入,或阻塞程序,使用时最好给出提示信息
c = input(‘请输入你的密码:’)
print(c)
存储单位
数据类型
进制转换
数据类型
说明:编程语言中不同的数据类型都是为了解决生活中的实际问题而出现的,每种类型都有相关的运算。
python中常用数据类型:整形、浮点、布尔、字符串、列表、元组、字典、集合等
整型(int):就是数学中的整数
浮点(float):就是数学中的小数
# 浮点
b = 3.14
print(b, type(b))
# 科学计数法
c = 3.1415926e-3
print(c, type(c))
复数(complex)
# 复数:了解
d = 2 + 3j
print(d, type(d))
布尔(bool):对应于生活中的真假逻辑,只有两个值True/False
空(NoneType):空类型,只有一个值None
字符串(str):使用引号括起来的一串字符
列表(list):通过[]进行定义,可以存放一系列的任意数据,是一种容器类型
lt = [1, 2, ‘hello’, 3.14, True]
print(lt, type(lt))
# 通过下标获取元素,有越界问题
print(lt[1])
元组(tuple):通过()进行定义,可以作为容器存放任意数据,元素是不可修改的
tp = (1, 2, [3, 4, 5])
print(tp, type(tp))
# 也是通过下标进行访问
print(tp[2])
# 定义一个元素的元组后面要添加一个,
tp2 = (1,)
print(tp2, type(tp2))
集合(set):通过{}进行定义,可以作为容器存放任意数据,但是元素是不能重复的,且是无序的
s1 = {‘李白’, ‘杜甫’, ‘白居易’, ‘王安石’, ‘苏轼’, ‘李白’}
s2 = {‘李白’, ‘李商隐’, ‘李清照’, ‘李贺’, ‘李煜’, ‘苏轼’}
# print(s1, type(s1))
# 交集
print(s1 & s2)
# 并集
print(s1 | s2)
# 差集
print(s1 - s2)
print(s2 - s1)
# 定义空集合不能使用{},这是留给定义空字典使用的
# 应该使用set()
# s3 = {}
# print(type(s3))
s4 = set()
print(type(s4))
集合经常用于去重操作
字典(dict):通过{}进行定义
元素是由键值对组成的
键和值之间是有’:'进行连接
键是唯一的,而值可以是任意的
示例:
d = {‘name’: ‘dahua’, ‘age’: 18}
print(d, type(d))
print(d[‘name’])
print(d.get(‘age’))
print(d.get(‘height’))
print(d.get(‘weight’, 75))
print(len(d))
print(len(s1))
print(len(lt))
print(len(‘helloworld’))
类型转换
隐式类型转换:混合运算、条件判断
强制类型转换:使用专门的函数进行转换
int:转换为整型
float:转换为浮点
str:转换为字符串
list:转换为列表
tuple:转换为元组
set:转换为集合
dict:转换为字典
示例:
# 转换为整数
# a = int(3.14)
# 参数1:需要转换的数据
# base:数据的进制类型,默认为十进制
# a = int(‘123’, base=8)
# a = int(‘abc’, base=16)
# 浮点
# a = float(250)
# 字符串
# a = str(123)
# 列表
# a = list('hello')
# a = list((1, 2, 3))
# a = list({1, 2, 3})
# 可以转换不会报错,但是只保留了键
# a = list({'name': 'ergou', 'age': 18})
# 元组
# a = tuple([1, 2, 3])
# 集合
# a = set([1, 2, 3])
# 字典
lt = [('name', 'dahua'), ('age', 18)]
a = dict(lt)
print(a, type(a))
类型相关操作
字符串
s1 = ‘hello’
s2 = ‘world’
# 可以使用’+'将字符串拼接在一起
s3 = s1 + s2
print(s3)
# '*'可以重复前面的字符串若干次
s4 = 'abc' * 3
print(s4)
# len函数统计字符串长度
print(len(s1))
s = 'abcdefg'
# 从开头进行提取,下标从0开始
print(s[0])
# 从末尾进行提取,下标从-1开始
print(s[-1])
# 切片
# 格式:s[开始:结束:步进]
print(s[1:3])
# 当一边的边界省略,则提取到改侧的边缘
print(s[1:])
print(s[:4])
print(s[1:-2])
print(s[:-3])
print(s[-3:])
# 指定步进值,默认为1
print(s[::2])
# 逆序提取
print(s[::-1])
# 格式化
# %s:字符串
# %d:整型
# %f:浮点
# %c:字符
name = '二狗'
like = '大花'
age = 18
print('俺叫%s,暗恋%s,她今年%d岁' % (name, like, age))
# python中特有的解决方案
print('俺叫{},暗恋{},她今年{}岁'.format(name, like, age))
print('俺叫{2},暗恋{1},她今年{0}岁'.format(name, like, age))
print('俺叫{l},暗恋{n},她今年{a}岁'.format(n=name, l=like, a=age))
列表
lt = [1, 2, 3, 4, 5]
print(lt[0])
print(lt[-1])
print(lt[1:3])
print(len(lt))
# 修改元素
lt[0] = 100
# 追加元素,将传递的元素作为一个整体(一个元素)追加到列表尾部
lt.append(200)
# lt.append([300, 400])
# 将可迭代对象的元素展开添加到列表中 (扩充)
lt.extend([300, 400])
# 插入元素,在指定位置插入元素
lt.insert(2, 250)
lt.insert(4, 250)
# 删除元素
# 根据索引号删除
del lt[0]
# 根据值进行删除,只会删除第一个
lt.remove(250)
# 返回并删除:返回并删除指定下标的元素,默认是最后一个
ele = lt.pop(2)
# print(ele)
# print(lt)
lt = [1, 2, 3, 4, 5, 3]
# 查询元组在列表中的索引号
# 找到就会返回其索引号,即第一个出现的位置
# 若不在列表中则会报错
print(lt.index(3))
# 统计元素在列表中出现的次数
print(lt.count(3))
# 逆序
lt.reverse()
# 排序
# reverse=True表示降序排序
lt.sort(reverse=True)
print(lt)
ASCII
运算符与分支结构
运算符
、>=、<、<=、==、!=
:按位右移,右移一位相当于除2
流程控制
相关类型操作
字符串切片
列表操作
元组操作
# tp1 = (1, 2, 3)
# tp1 = (1,)
tp1 = 1, 2, 3
tp2 = (4, 5, 6)
# 可以直接拼接在一起
# tp3 = tp1 + tp2
# print(tp3, type(tp3))
# 重复指定次数
tp4 = tp1 * 3
print(tp4)
# 统计元素个数
print(len(tp4))
tp = (1, 2, 3, 4, 5, 6)
# 切片操作
print(tp[0], tp[-1])
print(tp[1:-1])
# 获取指定元素的索引
print(tp.index(3))
# 统计元素出现的次数
print(tp.count(3))
# 最大值
print(max(tp))
# 最小值
print(min(tp))
集合操作
s = {‘彦炯’, ‘露露’, ‘彦博’, ‘启明’, ‘吕威’, ‘二狗’}
# 添加元素
s.add('继光')
# 删除元素
# s.remove('二狗')
# 删除不存在元素会报KeyError错
# s.remove('狗蛋')
# 删除元素,元素存在则删除,不存在也不报错
s.discard('狗蛋')
# 返回并删除,元素是随机的
# print(s.pop())
# 清空元素
s.clear()
# print(s)
s1 = {'小马', '小乔', '小周'}
s2 = {'小王', '小杜', '小马', '小乔', '小周'}
# 并集
# print(s1.union(s2))
# 交集
# print(s1.intersection(s2))
# 求交集,并用交集覆盖原来的集合
# s1.intersection_update(s2)
# 差集
# print(s1.difference(s2))
# 求差集,并用差集覆盖原来的集合
# s1.difference_update(s2)
# print(s1)
# 判断是否没有交集
print(s1.isdisjoint(s2))
# 判断是否是另一集合的子集
print(s1.issubset(s2))
# 判断是否是另一集合的父集/超集
print(s2.issuperset(s1))
字典操作
d = {‘name’: ‘xiaoming’, ‘age’: 20}
# 获取元素
# 有就返回对应的值,没有就报KeyError错
print(d['name'])
# 有就返回对应的值,没有就返回None,可以指定默认值
print(d.get('namexxx', '默认值'))
# 修改元素
# 键存在则修改对应的值
d['name'] = '二狗'
# 键不存在则添加键值对
d['height'] = 180
# 更新:存在的键会覆盖,不存在的键会添加
d.update({'name': 'dahua', 'weight': 50})
# 删除元素
# del d['weight']
# 返回并删除
print(d.pop('weight'))
# 清空元素
d.clear()
print(d)
练习
从终端获取一个表示年份的整数,判断是否是闰年,是就打印xxx年是闰年,不是就打印xxx年是平年
'''a=int(input('请输入一个年份'))
if (a % 4 ==0 and a % 100!=0) or (a % 400==0):
print(a,'年是闰年')
else:
print('是平年')'''
输入两个整数,打印较大值
'''a = (8,20)
print(max(a))'''
'''a = int(input('请输入第一个数字'))
b = int(input('请输入第二个数字'))
if a > b:
print(a)
else:
print(b)'''
输入三个整数,按照从小到大的顺序打印
# a = int(input('请输入第一个整数:'))
# b = int(input('请输入第二个整数:'))
# c = int(input('请输入第三个整数:'))
# lt=list((a,b,c))
# lt.sort()
# print(lt)
输入一个整数,判断其是否能同时被3和7整除
'''a = int(input('请输入一个数字'))
if a % 3 ==0 and a % 7 ==0:
print(a,'能被3和7整出')
else:
print(a,'不能被3和7整除')'''
输入一个字符,是大写转换为小写,小写转换为大写,其他字符保持不变,然后输出
ch = input('亲输入一个字符:')
asc = ord(ch)
#if 65<=asc<=90: #判断字符大小写
if 'A'<= ch <='Z':
print('是大写,转换后:',chr(asc+32) )
#elif 97<=asc<=122: #判断字符大小写
elif 'a'<= ch <='z':
print('是小写,转换后:',chr(asc-32))
else:
print(ch)
循环结构
循环结构(while)
循环结构(for-in)
列表生成式
range:
# 一个对象,保存了产生连续整数的算法,可以节约空间
# 可以指定起始位置,默认为0
# print(range(10))
# 可以进行遍历
for i in range(10):
print(i)
# 可以转换为列表
print(list(range(2, 10)))
列表生成式
# 列表生成式:可以快速方便地生成列表
print([i for i in range(1, 11)])
print([i for i in ‘abcdefg’])
print([i2 for i in range(1, 11)])
print([ii for i in range(1, 11)])
print([str(i) for i in range(1, 11)])
print([i for i in range(1, 11) if i % 2 == 0])
# 生成的列表可以与遍历的内容没有一毛钱关系
print([250 for i in range(1, 11)])
循环嵌套
循环能否嵌套
循环嵌套示例
# 外层循环控制打印多少行
for i in range(1, 11):
# print(’’ * i)
# 内存循环控制每一行多少个
for j in range(i):
print(’’, end=’ ')
print()
练习:使用while实现一遍
思考:列表排序实现,冒泡排序法思路(升序排序)
lt = [8, 3, 6, 9, 5, 2, 4, 1, 7]
第一轮:[3, 6, 8, 5, 4, 1, 7, 9]
第二轮:[3, 6, 5, 4, 1, 7, 8, 9]
第三轮:[3, 5, 4, 1, 6, 7, 8, 9]
参考示例:
lt = [8, 3, 6, 9, 5, 2, 4, 1, 7]
n = len(lt)
for i in range(n-1):
# 内存循环控制相邻两个元素的比较
for j in range(n-1-i):
if lt[j] > lt[j+1]:
# 通用交换元素方式
# temp = lt[j]
# lt[j] = lt[j+1]
# lt[j+1] = temp
# python中特有方式
lt[j], lt[j+1] = lt[j+1], lt[j]
print(lt)
选择排序
思路:先取出一个位置,用该位置的元素与后面的所有元素挨个比较,不合适就发生交换。
示例:lt = [8, 3, 6, 9, 5, 2, 4, 1, 7]
第一轮:1, 8, 6, 9, 5, 3, 4, 2, 7
第二轮:1, 2, 8, 9, 6, 5, 4, 3, 7
第三轮:1, 2, 3, 9, 8, 6, 5, 4, 7
字符串操作
切割与拼接
s = ‘I love you more than i can say’
# 切割字符串
# sep:指定按照什么进行切割,默认按照空格切割
# maxsplit:指定最大切割次数,默认不限制次数
# ret = s.split(sep=‘abc’, maxsplit=1)
# 从右边进行切割
ret = s.rsplit(’ ', maxsplit=1)
print(ret)
s = 'Hello\nworld'
# 按照换行进行切割
print(s.splitlines())
s = 'I love you more than i can say'
ret = s.split()
# print(ret)
# 字符串拼接
s2 = '*'.join(ret)
print(s2)
查找统计判断
s = ‘Hi buddy, if you have something to say, than say; if you have nothing to say, than go.’
# 子串查找:找到首次出现的位置,返回下标,找不到返回-1
# ret = s.find('hello')
# 从后面查找
# ret = s.rfind('to')
# 统计子串出现的次数
# ret = s.count('if')
# 判断是否已指定内容开头
# ret = s.startswith('Hi')
# 判断是否已指定内容结尾
ret = s.endswith('go.')
print(ret)
转换及替换
s = ‘hellO worlD!’
# 转换为全大写
print(s.upper())
# 转换为全小写
print(s.lower())
# 大小写转换
print(s.swapcase())
# 首字母大写
print(s.capitalize())
# 每个单词首字母大写
print(s.title())
# 用指定的内容替换指定内容,还可以值替换次数
print(s.replace(‘l’, ‘L’, 2))
类型判断
s = ‘abcABC2’
# 是否是全大写
print(s.isupper())
# 是否是全小写
print(s.islower())
# 是否每个单词首字母都大写
print(s.istitle())
# 是否是全数字字符
print(s.isdecimal())
# 是否是全字母
print(s.isalpha())
# 是否全是字母或数字
print(s.isalnum())
练习
计算1~100之间所有整数的和
'''a = 0
i = 0
while a < 100:
a+=1
i+=a
print(i)'''
print([chr(i) for i in range(ord('A'),ord('Z')+1)])
循环输入10个字符,大写转小写,小写转大写,其它字符不变,然后输出
'''a = 1
while a<=10:
ch = input('亲输入一个字符:')
asc = ord(ch)
# if 65<=asc<=90: #判断字符大小写
if 'A' <= ch <= 'Z':
print('是大写,转换后:', chr(asc + 32))
# elif 97<=asc<=122: #判断字符大小写
elif 'a' <= ch <= 'z':
print('是小写,转换后:', chr(asc - 32))
else:
print(ch)
a+=1'''
将12345转换为54321
n = 12345
ret = 0
while n :
#获取最后一位
last = n % 10
#求商
n = n // 10
#原来的结果乘以10 然后加上本次得到的数
ret = ret * 10 +last
print(ret))
‘’'n = 12345
ret = 0
while n :
#获取最后一位
last = n % 10
#求商
#一次性得到商和余数
n,last=divmod(n,10)
#原来的结果乘以10 然后加上本次得到的数
ret = ret * 10 +last
print(ret)’’’
将12345转换为’12345’,不要使用str
n = 12345
ret = ''
while n:
n,last=divmod(n,10)
ch = chr(last + ord('0'))
ret = ch + ret
print(ret,type(ret))
将’12345’转换为12345,不要使用int
遍历列表,打印:我叫name,今年age岁,家住dizhi,电话phone
lt = [
{‘name’:‘小王’, ‘age’:18, ‘info’:[(‘phone’, ‘123’), (‘dizhi’, ‘广州’)]},
{‘name’:‘小芳’, ‘age’:19, ‘info’:[(‘phone’, ‘789’), (‘dizhi’, ‘深圳’)]},
{‘name’:‘小杜’, ‘age’:22, ‘info’:[(‘phone’, ‘567’), (‘dizhi’, ‘北京’)]},
{‘name’:‘小孟’, ‘age’:28, ‘info’:[(‘phone’, ‘000’), (‘dizhi’, ‘上海’)]},
{‘name’:‘小乔’, ‘age’:26, ‘info’:[(‘phone’, ‘111’), (‘dizhi’, ‘河南’)]},
]
for i in lt:
name=i['name']
age=i['age']
#取出info中下标为1的元素中的下标为1的元素值
dizhi=i['info'][1][1]
phone=i['info'][0][1]
print('我叫{},今年{},家住{},电话{}'.format(name,age,dizhi,phone))
打印九九乘法表
#外层循环控制打印多少行
for i in range(1,10):
#内层控制每行怎么打印
for j in range(1,i+1):
print("%d*%d=%2d" % (j,i,i*j),end=" ")
print (" ")'''
从终端输入两个整数m和n,打印m*n的表格,如:2,5,打印如下图形:
1 2 3 4 5
6 7 8 9 10
m = int(input(“请输入一个数字”))
n = int(input(“请输入一个数字”))
for i in range(m):
for j in range(1,n+1):
num = j + i* n
print(num,end=" ")
print()
函数基础
函数简介
函数使用
函数分类
说明:按照有无参数及返回值来分
示例:
# 无参无返回值
def print_ten_hello():
for i in range(10):
print(‘hello world!’)
# 无参:调用时无需传参数
# 无返回值:执行完函数的返回值为None
# None的一个作用是为了不报错,仅仅只是这样
# ret=print_ten_hello()
# print(print_ten_hello())
#
# 带参无返回值
def print_n_hello(n):
for i in range(n):
print('hello world!')
# 需要传递参数
print_n_hello(3)
# 带参有返回值
def add(a, b):
ret = a+b
# 使用关键字return返回内容
# 一旦执行return,函数立即结束
# return后面会返回函数返回值
return ret
print(add(3,5))
函数参数
形参:形式参数,就是写在函数定义处的参数。
实参:实际参数,就是在函数调用时传递的参数。
位置参数:函数定义时没有默认值的参数,也叫必传参数。调用时实参与定义时的形参要一一对应
默认参数:函数定义时有默认值的参数,调用函数时可以不传递该参数。默认参数需要放在末尾
关键字参数:函数调用时指定参数的名字,参数的位置就无需考虑。
可变长度参数:
def var_len_args(a, b, *args, name=‘二狗’, **kwargs):
print(a, b)
# 是一个元组,用于保存多传的位置参数
print(args)
# 是一个字典,用于保存多传的关键字参数
*的使用
def show(a, b=8):
print(a, b)
lt = [2, 3]
# show(lt[0], lt[1])
# 与上式等价,*是将列表展开,然后作为位置参数传递给函数
show(*lt)
d = {'a': '大花', 'b': 18}
# show(a=d['a'], b=d['b'])
# 与上式等价,**式将字典展开,然后作为关键字参数传递给函数
show(**d)
函数进阶
常用函数
内置函数(无需导入)
print:打印,输出
input:输入
type:获取类型
len:统计元素个数
range:产生连续的整数对象
enumerate:枚举可迭代对象
ord:字符转ASCII
chr:ASCII转字符
abs:求绝对值
类型转换:int、float、str、bool、set、list、tuple、dict
max:最大值
min:最小值
sum:求和
pow:求幂
round:四舍五入
hex:十六进制
oct:八进制
bin:二进制
模块函数(需要导入)
import time
#
# while True:
# print(‘Hello world!’)
# time.sleep(1)
import math
print(math.e)
print(math.pi)
print(math.ceil(3.1))
print(math.floor(3.9))
print(math.sqrt(4))
# 度转换为弧度
print(math.radians(360))
# 弧度转换为度
print(math.degrees(math.pi))
import sys
# 是一个列表,保存所有的命令行参数
print(sys.argv)
练习
前面的练习使用函数封装一下
实现一个终端计算器,如:python test.py 3 + 5,结果:8
删除列表中重复的元素,要求元素的顺序不变
lt = [1, 2, 3, 4, 5, 3, 6, 8, 2]
def quchong(lt):
lt2 = []
for i in lt:
# 当前元素不在新列表中,就追加到列表后面
if i not in lt2:
lt2.append(i)
return lt2
lt2 = quchong(lt)
print(lt2)
统计一个字符串中字母、数字、其它字符的个数,返回一个元组
def tj(s):
zimu = 0
num = 0
qita = 0
for i in range(len(s)):
if (s[i]>='a' and s[i]<='z') or (s[i]>='A' and s[i]<='Z'):
zimu+=1
elif s[i]>='0' and s[i]<='9':
num+=1
else:
qita+=1
return (zimu,num,qita)
s=input('请输入字符串')
print(tj(s))
返回一个列表中第二大的数
字符串解析:号码归属地查询
‘’‘5582|1860101|010|北京市|北京联通GSM卡
5583|1860100|010|北京市|北京联通GSM卡
5584|1368141|010|北京市|北京移动神州行卡
5585|1860111|010|北京市|北京联通GSM卡
5586|1358198|010|北京市|北京移动动感地带卡
5587|1361139|010|北京市|北京移动预付费卡
5588|1361138|010|北京市|北京移动神州行卡
5591|1360110|010|北京市|北京移动全球通卡
5748|1364110|010|北京市|北京移动神州行卡
10186|1581584|020|广东省广州市|广东移动全球通卡
15046|1391897|021|上海市|上海移动全球通卡
17250|1502207|022|天津市|天津移动全球通卡
21137|1345272|023|重庆市万州|重庆移动大众卡
22700|1347812|024|辽宁省沈阳市|辽宁移动大众卡
24256|1377065|025|江苏省南京市|江苏移动全球通卡
26360|1898606|027|湖北省武汉市|湖北电信CDMA卡
28709|1860802|028|四川省成都市|四川联通GSM卡
30641|1552961|029|陕西省西安市|陕西联通GSM卡
31700|1563007|0310|河北省邯郸市|河北联通GSM卡
33360|1583396|0311|河北省石家庄市|河北移动全球通卡
34825|1508122|0312|河北省保定市|河北移动全球通卡
35363|1551235|0313|河北省张家口|河北联通GSM卡
37700|1331326|0316|河北省廊坊市|河北电信CDMA卡
43500|1350358|0358|山西省吕梁市|山西移动全球通卡
43908|1553625|0359|山西省运城市|山西联通GSM卡
44521|1335360|0370|河南省商丘市|河南电信CDMA卡
50078|1509369|0378|河南省开封市|河南移动全球通卡
53603|1583981|0398|河南省三门峡|河南移动全球通卡
53916|1335897|0410|辽宁省铁岭市|辽宁电信CDMA卡
55248|1554254|0411|辽宁省大连市|辽宁联通GSM卡
58618|1374272|0427|辽宁省盘锦市|辽宁移动全球通卡
58932|1554183|0429|辽宁省葫芦岛|辽宁联通GSM卡
60268|1340475|0431|吉林省长春市|吉林移动大众卡’’’
def chaxun(haoma):
set = a.split(’\n’)
n=len(set)
dt = {}
for i in range(n):
set1=set[i].split(’|’)
dt.update({set1[1]:set1[4]})
print(‘号码区域为:’,dt.get(haoma),sep=’’)
while True:
haoma=input(‘请输入号码:’)
chaxun(haoma)
函数使用
变量作用域
块级作用域
if True:
name = ‘xiaoming’
# 没有块级作用域
print(name)
局部作用域
def test():
a = 10
test()
# 局部变量:在函数内部定义的变量,只能在函数内部使用
# print(a)
全局作用域
# 全局变量:定义在函数外部的变量,拥有全局的作用
num = 10
def show():
# 函数内部可以使用外部定义的变量
# print(num)
# 若想更改外部变量,需要进行global声明
global num
# 不能更改外部的全局变量,而是定义了一个局部变量
num = 20
show()
print(num)
nonlocal使用
def wai():
n = 100
def nei():
# 使用外部函数的局部变量,需要进行声明才可更改
nonlocal n
# 内部函数可以使用外部函数的局部变量,但是不能更改
n = 200
print(n)
nei()
print(n)
wai()
匿名函数
函数可以像普通变量一样进行赋值
def test():
print(‘for test’)
print(test.__name__)
# 函数可以像普通变量一样进行赋值
a = test
print(a.__name__)
a()
函数可以作为一个函数的参数
def show(func):
func()
# 函数作为参数传递
show(test)
匿名函数
说明:当将函数作为参数传递时,若函数只需要一次,没有必要单独定义函数,可以使用匿名函数解决。
格式:lambda 参数列表: 表达式
示例:
lt = [
{‘name’: ‘dahua’, ‘age’: 18, ‘height’: 165},
{‘name’: ‘erhua’, ‘age’: 16, ‘height’: 160},
{‘name’: ‘dagou’, ‘age’: 20, ‘height’: 175},
{‘name’: ‘ergou’, ‘age’: 15, ‘height’: 155}
]
def key(d):
return d[‘height’]
lt.sort(key=lambda d: d[‘age’])
for i in lt:
print(i)
闭包使用
定义:具有执行环境的函数
示例:
def wai(n):
# 定义内部函数
def nei():
# 内部函数中使用外部函数的局部变量
return n * n
# 内部函数作为返回值
return nei
f1 = wai(10)
f2 = wai(4)
print(f1())
print(f2())
装饰器
作用:当需要改变一个函数原有的功能时,但是不想/不能改变原来的函数,可以通过装饰器解决
使用:
示例:
def zhuangshiqi(func):
def wrapper():
print(‘开始装饰’)
func()
print(‘装饰结束’)
return wrapper
@zhuangshiqi
# 相当于执行了:test = zhuangshiqi(test)
def test():
print('for test')
# t2 = zhuangshiqi(test)
# t2()
# test = zhuangshiqi(test)
test()
@zhuangshiqi
def demo():
print('原有内容')
demo()
分类:
装饰无参无返回值的函数
def shuai(func):
def wrapper():
print(‘拉风的暴龙眼镜’)
func()
print(‘鳄鱼牌大头皮鞋’)
return wrapper
@shuai
def diaosi():
print('杰哥,屌丝一枚')
diaosi()
装饰带参无返回值的函数
def zhuangshiqi(func):
def wrapper(*args, **kwargs):
print(‘开始装饰’)
func(*args, **kwargs)
print(‘装饰结束’)
return wrapper
@zhuangshiqi
def test(n):
print(‘I like num {}’.format(n))
test(250)
装饰带参有返回值的函数
def zhuangshiqi(func):
def wrapper(*args, **kwargs):
print(‘开始装饰’)
ret = func(*args, **kwargs)
print(ret)
print(‘装饰结束’)
return ret
return wrapper
@zhuangshiqi
def add(a, b):
return a + b
print(add(3, 5))
递归函数(了解)
求n的阶乘
def he(n):
if n ==1:
return n
return he(n-1)*n
print(he(5))
斐波那契数列的第n项
示例:1, 1, 2, 3, 5, 8, 13, 21, 34, …
lis =[]
for i in range(20):
if i ==0 or i ==1:#第1,2项 都为1
lis.append(1)
else:
lis.append(lis[i-2]+lis[i-1])#从第3项开始每项值为前两项值之和
print(lis)
#输出第几个斐波那契数字
def fib(n):
a,b=1,1
for i in range(n-1):
a,b =b,a+b
return a
print(fib(10))
练习:
实现列表排序sort函数,要求支持任意类型元素的排序,也支持降序
‘’‘lt = [2,1,5,8,4,3]
def list_sort(lt,key=None,reveres=False):
n = len(lt)
for i in range(n-1):
for j in range(n-1-i):
if key:
if reveres:
if key(lt[j]) < key(lt[j + 1]):
lt[j], lt[j + 1] = lt[j + 1], lt[j]
else:
if key(lt[j]) > key(lt[j + 1]):
lt[j], lt[j + 1] = lt[j + 1], lt[j]
else:
if reveres:
if lt[j] < lt[j+1]:
lt[j],lt[j+1]=lt[j+1],lt[j]
else:
if lt[j] > lt[j+1]:
lt[j],lt[j+1]=lt[j+1],lt[j]
list_sort(lt,reveres=True)
for i in lt:
print(i)’’’
计算一个字符串中所有数字的和
def num(a):
sum = 0 # 设置变量 保存和
for i in range(len(a)): #遍历字符串
if a[i]>='0' and a[i]<='9': #根据下标看是否是数字
sum = sum+int(a[i]) # 数字转换为整数 相加求和
return sum
a = input('请输入数字')
print(num(a))
实现一个字符串逆序的函数
def nixu(a):
n = len(a)
for i in range(n):
for j in range(n-1):
s = []
s.append(i)
return s
返回一个列表中出现次数最多的元素
def duo(n):
a = 0
for i in n:
if n.count(i) > a:
s = i
a = n.count(i)
return s
n = [1,2,3,4,5,5,5,6,7,8,9,9,9,9,9]
print(duo(n))
lt = [‘小马’,‘小敏’,‘小乔’,‘小敏’,‘小杜’,‘小蒙’,‘小敏’]
def max_count(lt):
#定义一个字典用于存放元素及出现的次数
d = {}
#记录最大的次数的元素
max_key=None
#遍历列表 统计每个元素出现的次数 然后保存到字典
for i in lt:
if i not in d:
#计算元素出现的次数
count = lt.count(i)
#保存到字典中 最多的元素为键 次数为值
d[i] = count
#记录次数最大元素
if count > d.get(max_key,0):
max_key = i
return max_key
print(max_count(lt))
#直接统计 简单统计
print(max(lt,key=lt.count))
from collections import Counter
c = Counter(lt)
print(dict©)
函数使用
零碎知识
灵活的if-else
a = 3 if False else 5
# 上下两种写法等价
# if False:
# a = 3
# else:
# a = 5
print(a)
灵活的and/or
# 前面的表达式为真,才会执行后面的表达式
a = True and 3
print(a)
# 前面的表达式为假,后面的表达式根本无需执行
b = False and 5
print(b)
# 前面的表达式为真,后面的表达式无需执行
c = True or 3
print(c)
# 前面的表达式为假,需要后面表达式的判断
d = False or 5
print(d)
类型判断
a = 250
# print(type(a))
# if type(a) == int:
if type(a) == type(1):
print(‘a’, ‘是一个整数’)
# 判断一个对象是不是某种类型的一个实例
print(isinstance(a, int))
print(isinstance(a, str))
def test():
pass
# print(type(test))
# 用能使用这种方式进行函数类型的判断
# print(isinstance(test, function))
from inspect import isfunction
# 判断一个标识符是否是函数
print(isfunction(test))
print(isfunction(a))
变量地址
# 获取变量地址
print(id(a))
b = 10
print(id(b))
# a和b地址相同
lt = [1, 2, 3]
print(id(lt))
lt2 = [1, 2, 3]
print(id(lt2))
# lt和lt2地址不同
生成器
使用场景:
在使用列表时,很多时候我们不会一下子使用数据,通常都是一个一个使用;当数据量较大的时候,定义一个列表会使程序内存占用突然增大,为了解决此类问题,python中引入了生成器。
生成方式:
方式1:将列表生成式的[]改为()即可
lt = (i for i in range(3))
print(lt)
print(next(lt))
print(next(lt))
print(next(lt))
print(next(lt))
方式2:在函数中使用yield关键字
‘’’
def test(n):
lt = []
for i in range(1, n+1):
lt.append(i)
return lt
print(test(10))
‘’’
def test(n):
for i in range(1, n+1):
# 执行到此处,函数会返回yield后的内容,然后会停止在这里
yield i
t = test(3)
print(list(t))
使用说明:
迭代器
可迭代对象
前面学习过的字符串及容器类型的对象都是可迭代对象
迭代器一定是可迭代对象
判断一个对象是否是可迭代对象
from collections import Iterable, Iterator
lt = [1, 2, 3]
print(isinstance(lt, Iterable))
print(isinstance(lt, Iterator))
iter:可以将可迭代对象转换为迭代器
lt = [1, 2, 3]
lt2 = iter(lt)
random
示例:
import random
# 生成指定范围内的随机整数
print(random.randint(1, 10))
# 生成0~1之间的随机小数
print(random.random())
# 生成指定范围内的随机整数,可以指定步幅
print(random.randrange(1, 10, 2))
lt = [1, 2, 3, 4, 5, 6, 7]
# 从容器对象或字符串中随机挑选一个元素
print(random.choice(lt))
# print(random.choice('ashdaiapo'))
# 从容器对象中随机挑取指定个数的元素
print(random.sample(lt, 3))
# 从容器对象中随机挑取一个元素,sample函数个数为1的情况
print(random.choices(lt))
# 打乱一个列表
random.shuffle(lt)
print(lt)
高级函数
map
参数:
func:一个函数
iter:一个可迭代对象
功能:
将可迭代对象遍历,每个元素都使用该函数处理一遍,然后返回,保存这种算法的迭代器
使用:
from collections import Iterator
lt = [1, 2, 3, 4, 5]
def pingfang(n):
return n * n
ret = map(lambda x: x*x, lt)
print(isinstance(ret, Iterator))
print(list(ret))
练习:
filter
参数
function:一个函数
iterable:可迭代对象
功能:
使用function依次作用于可迭代对象中的每个元素,当返回结果为True时保留该元素。返回filter对象,是一个迭代器。
示例:
lt = [1, 2, 3, 4, 5]
def oushu(n):
return n%2 == 0
ret = filter(lambda x: x%2 != 0, lt)
print(ret)
print(list(ret))
练习:使用filter函数,提取一个任意列表中长度大于3的字符串元素。
reduce
参数
function:一个函数
sequence:一个序列
功能:
示例:
from functools import reduce
lt = [1, 2, 3, 4, 5]
def add(a, b):
return a + b
ret = reduce(lambda x, y: x*10 + y, lt)
print(ret)
练习:使用reduce函数实现,求一个列表中所有元素的乘积
练习
使用random函数实现randint函数的功能
第一种
import random
def my_randint(m,n):
return round(random.random()*(n-m)+m)
my_randint(1,10)
print(my_randint(1,10))
第二种
import random
print(random.randint(1,100))
print(random.random())
def rand_int(start,stop):
return round(random.random() * (stop-start)+start)
print(rand_int(1,10))
生成指定长度的随机字符串,参数:长度、类型
from random import randint,choice,sample,random
def rand_str(l=6,t=0):
s = ''
if t == 0: #纯数字
for i in range(6):
# s = s+chr(randint(ord('0'),ord('9')))
s = s+str(randint(0, 9))
elif t == 1: #纯字母
base_str= 'abcdefghjklmnopqrstuvwxyz'
# s=''.join(sample(base_str,l))
s = ''.join(choice(base_str)for i in range(l))
else: #数字字母混合
s =.join(choice('0123456789abcdefghjklmnopqrstuvwxyz')for i in range(l))
# s = sample(s,l)
return s
print(rand_str(l=6,t=2))
字符串转换,如:‘IloveYOUmoreTHANiCANsay’ => ‘I love you more than i can say’
s = 'IloveYOUmoreTHANiCANsay'
def sep_word(s):
# ret = s[0].upper()
# for i in range(1,len(s)):
# if s[i].isupper() ==s[i-1].islower():
# ret = ret+' '
# ret = ret+s[i].lower()
# return ret
# ret = s[0]
# for i in range(1, len(s)):
# if s[i].isupper() == s[i - 1].islower():
# ret = ret + ' '
# ret = ret + s[i]
# return ret.capitalize()
ret=''
for i in range(len(s)-1):
ret +=s[i]
if s[i].isupper() == s[i+1].islower():
ret +=' '
ret +=s[-1]
return ret.capitalize()
print(sep_word(s))
将列表元素完成特定的移动操作,参数:列表、移动位数(正数表示右移,负数表示左移)
lt = [1,2,3,4,5,6]
def shift(lt,step):
step %= len(lt)
# for i in range(step):
# #弹出最后一个元素
# last=lt.pop()
# #插入到开头
# lt.insert(0,last)
#提取左半部分
left = lt[:-step]
#提取右半部分
right = lt[-step:]
#清空列表
lt.clear()
#将右半部分添加到列表
lt.extend(right)
#将左半部分添加到列表
lt.extend(left)
shift(lt,2)
print(lt)
使用递归,完成以下功能:传入n,返回:1! + 2! + 3! + … + (n-1)! + n!
def jh(n):
if n==1:
return 1
elif n == 2:
return 3
return jh(n-1)+n*(jh(n-1)-jh(n-2))
print(jh(1))
print(jh(2))
print(jh(3))
歌词解析:解析成一个时间戳一句歌词的形式,封装函数(根据时间返回歌词)
[ti:蓝莲花]
[ar:许巍]
[al:留声十年绝版青春北京演唱会]
[00:-01.70]蓝莲花
[00:-00.70]演唱:许巍
[00:00.00]
[00:00.70]没有什么能够阻挡
[00:06.01]你对自由的向往
[00:11.43]天马行空的生涯
[00:16.99]你的心了无牵挂
[00:21.20]
[02:11.55][01:50.60][00:22.63]穿过幽暗的岁月
[02:16.93][01:55.60][00:27.81]也曾感到彷徨
[02:22.21][02:01.09][00:33.13]当你低头的瞬间
[02:27.62][02:06.33][00:38.32]才发觉脚下的路
[02:31.64][02:10.23][00:42.37]
[02:32.97][00:43.79]心中那自由的世界
[02:38.23][00:49.50]如此的清澈高远
[02:43.30][00:54.31]盛开着永不凋零
[02:47.70][00:58.50]蓝莲花
[02:53.95][03:00.06][01:05.41]
s = '''[ti:蓝莲花]
[ar:许巍]
[al:留声十年绝版青春北京演唱会]
[00:-01.70]蓝莲花
[00:-00.70]演唱:许巍
[00:00.00]
[00:00.70]没有什么能够阻挡
[00:06.01]你对自由的向往
[00:11.43]天马行空的生涯
[00:16.99]你的心了无牵挂
[00:21.20]
[02:11.55][01:50.60][00:22.63]穿过幽暗的岁月
[02:16.93][01:55.60][00:27.81]也曾感到彷徨
[02:22.21][02:01.09][00:33.13]当你低头的瞬间
[02:27.62][02:06.33][00:38.32]才发觉脚下的路
[02:31.64][02:10.23][00:42.37]
[02:32.97][00:43.79]心中那自由的世界
[02:38.23][00:49.50]如此的清澈高远
[02:43.30][00:54.31]盛开着永不凋零
[02:47.70][00:58.50]蓝莲花
[02:53.95][03:00.06][01:05.41]'''
# 定义一个字典,保存歌曲信息
song_dict = {}
# 定义一个字典,保存歌词信息
lrc_dict = {}
# 按照换行进行切割
str_list = s.splitlines()
for string in str_list:
# 判断是否是歌词信息
if string[1].isdecimal():
# [02:11.55][01:50.60][00:22.63]穿过幽暗的岁月
# 按照']'进行切割
lrc_list = string.split(']')
# 提取歌词信息
lrc_info = lrc_list[-1]
# 提取时间信息
time_info = lrc_list[:-1]
# 遍历处理每个时间戳
for time_str in time_info:
# [02:11.55,去掉'['
time_str = time_str[1:]
# 02:01.09,按照':'进行切割
time_info_list = time_str.split(':')
# 提取分钟
time_min = float(time_info_list[0])
# 提取秒数
time_sec = float(time_info_list[1])
# 合并时间
time = time_min * 60 + time_sec
# 保存歌词及对应的时间戳
lrc_dict[time] = lrc_info
else:
# [ti:蓝莲花]
# 去掉两边的[]
string = string[1:-1]
# 按照':'进行切割
song_list = string.split(':')
# 保存到字典中
if song_list[0] == 'ti':
song_dict['标题'] = song_list[1]
elif song_list[0] == 'ar':
song_dict['艺术家'] = song_list[1]
elif song_list[0] == 'al':
song_dict['专辑'] = song_list[1]
提取所有的时间戳
time_list = list(lrc_dict)
对时间戳进行降序排序
time_list.sort(reverse=True)
根据时间戳返回对应歌词
def get_lrc_by_time(t):
for i in time_list:
if i <= t:
return lrc_dict[i]
return lrc_dict[time_list[-1]]
下面的代码都是测试代码
import time
import os
t = 0
last_lrc = None
while True:
lrc = get_lrc_by_time(t)
if last_lrc != lrc:
# 清屏
os.system('cls')
for s in song_dict:
print(s, song_dict[s])
print()
last_lrc = lrc
print(lrc)
time.sleep(0.5)
t += 0.5
文件操作
目录管理(os)
示例:
import os
# 执行命令
# 清屏
# os.system('cls')
# 调出计算器
# os.system('calc')
# 操作系统类型,nt表示windows,posix表示类unix
# print(os.name)
# 获取环境变量
# print(os.environ['path'])
# print(os.environ.get('pathxx', 'default'))
# 与上式等价
# print(os.getenv('pathxx', 'default'))
print(os.getenv('xxx', 'default'))
查看当前工作目录
print(os.getcwd())
创建目录
# 新建目录
# os.mkdir(‘test’)
# 不能创建中间目录,否则会失败
# os.mkdir(‘a/b/c’)
# 可以创建中间目录
os.makedirs(‘a/b/c’)
删除目录
# 删除目录
# os.rmdir(‘test’)
# 只能删除空目录,不能删除有内容的目录
os.rmdir(‘a’)
重命名
os.rename(‘test2’, ‘test’)
查看文件信息
stat = os.stat(‘01-os.py’)
print(stat.st_size)
查看指定目录内容
print(os.listdir(os.getcwd()))
path使用
import os
# 目录拼接
# print(os.path.join('abc/def', 'hello.py'))
# 提取目录
# print(os.path.dirname('abc/def/hello.py'))
# print(os.path.dirname('C:/Apache24/htdocs/code/day08'))
# 提取文件
# print(os.path.basename('abc/def/hello.py'))
# 切割路径与文件名
# dir, file = os.path.split("abc/def/hello.py")
# print(dir, file)
# 切割路径名与后缀
# print(os.path.splitext('abc/def/hello.py'))
# print(os.path.splitext('hello.py'))
# 判断文件是否存在,可以是目录
# print(os.path.exists('a'))
# 判断是否是目录
# print(os.path.isdir('01-os.py'))
# print(os.path.isdir('a'))
# 判断是否是文件
# print(os.path.isfile('01-os.py'))
# print(os.path.isfile('a'))
# 获取文件大小,只适用于文件,不能是目录
print(os.path.getsize('01-os.py'))
print(os.path.getsize('a'))
文件管理
打开文件
示例
fp = open(‘00-test.txt’)
参数
file:操作的文件名
mode:打开模式
encoding:编码方式,通常不指定,系统会自动识别
打开方式
r:只读方式,文件不存在会报错
w:只写方式,文件不存在则创建,存在则清空
a:追加方式,文件不存在则创建,存在则打开(不会清空内容),只能向末尾添加内容
r+:在r的基础上添加写的权限
w+:在w的基础上添加读的权限
a+:在a的基础上添加读的权限
在上面打开方式上添加一个字符’b’,表示已二进制方式进行操作:rb、wb、ab、rb+、wb+、ab+
说明:没有添加b的方式的打开,默认都是以字符串形式操作,带b的方式都是以bytes形式操作的
编码方式
ASCII:美国信息交换标准代码(128)
ansi:扩展的ASCII(256)
gb2312:中国的ansi
gbk:扩充的gb2312
unicode:万国码,能够将所有国家的所有字符进行统一编码
utf-8:可变长度的unicode实现方案,并且对中文支持良好
关闭文件
fp.close()
文件读写
# 判断是否可读
# print(fp.readable())
# 判断是否可写
# print(fp.writable())
# 读取指定长度内容,默认读取全部
# content = fp.read(5)
# print(content)
# 写操作
# fp.write('123')
操作位置
# 获取文件操作位置
print(fp.tell())
# 设置操作位置
# 参数1:偏移量
# 参数2:参考位置,0表示开头,1表示当前位置,2表示文件末尾
# 当以bytes方式操作时没有问题,但是以str方式操作时只能设置从开头的偏移
fp.seek(-3, 2)
bytes类型
示例:
# s = b’hello’
# print(s, type(s))
# 编码:str => bytes
s = 'hello'.encode('utf-8')
print(s)
# 解码:bytes => str
b = s.decode('utf-8')
print(b)
环境变量
文件目录
练习: 见第二周第五天代码
常用模块
time
calendar
示例:
import calendar
# 返回一年的日历
c = calendar.calendar(2018, w=3, l=2, c=2, m=2)
# print(c)
# 返回某一年的某一月的日历
m = calendar.month(2018, 11)
# print(m)
# 判断闰年
print(calendar.isleap(2008))
# 两个年份之间的闰年数量,区间:[起始,结束)
print(calendar.leapdays(2000, 2008))
print(calendar.leapdays(2000, 2009))
datetime
date
from datetime import date
import time
# 创建对象
d1 = date(2018, 11, 26)
# print(d1, type(d1))
d2 = date.today()
# print(d2)
d3 = date.fromtimestamp(time.time())
# print(d3)
# 标准格式显示
print(d1.isoformat())
# 日历显示:(年,第几周,星期)
print(d2.isocalendar())
# 获取星期,标准格式1~7
print(d3.isoweekday())
# 获取星期,格式0~6
print(d3.weekday())
# 格式化显示
print(d3.strftime('%Y/%m/%d'))
# 提取单独的年月日
print(d3.year, d3.month, d3.day)
# 转换为time.struct_time对象
print(d3.timetuple())
time
from datetime import time
# 创建对象
t = time(1, 2, 3)
print(t, type(t))
print(str(t))
# 单独获取时、分、秒
print(t.hour, t.minute, t.second)
# 格式化显示
print(t.strftime('%H::%M::%S'))
datetime
from datetime import datetime
import time
# 创建对象
dt = datetime(2018, 11, 26, 14, 53, 52)
# 当前时间,带时区
dt2 = datetime.now()
# 当前时间,不带时区
dt3 = datetime.utcnow()
# 转换时间戳
dt4 = datetime.fromtimestamp(time.time())
# print(dt4)
# 提取日期
d = dt.date()
print(d, type(d))
# 提取时间
t = dt.time()
print(t, type(t))
# 转换成时间戳
print(dt.timestamp())
# 格式化显示
print(dt.strftime('%Y/%m/%d %H/%M/%S'))
timedelta
from datetime import timedelta, datetime
td = timedelta(seconds=3600)
td2 = timedelta(days=2)
dt1 = datetime(2018, 11, 26, 15, 6, 10)
dt2 = datetime(2018, 11, 25, 14, 6, 10)
td3 = dt1 - dt2
# print(td3, type(td3))
dt3 = dt1 + td2
# print(dt3, type(dt3))
# 提取天数
print(td3.days)
# 提取秒数(天以外的)
print(td3.seconds)
# 总共的秒数
print(td3.total_seconds())
模块使用
定义:模块就是一个工具包,里面可以包含函数、类库等,使用时导入即可。
分类:
语法:
# 导入模块
import time
# 导入模块中指定的内容
from time import sleep
# 带入模块,并且起别名
import random as rdm
# 导入模块中的指定内容,并且起别名
from random import randint as rint
as
模糊导入
# 模糊导入,导入该模块中__all__列表指定的内容
# 不建议使用:
# 1.不知道导入了什么内容
# 2.多个模块中有同名的内容无法处理
from random import *
自定义模块
测试模块
# 直接执行此模块,值为__main__
# 被其他模块导入,值为模块名
# print(‘模块名:’, name)
# 模块测试内容可以这么写
# 当直接运行此模块时会执行,当被其他模块导入时不会执行
if __name__ == '__main__':
print('模块测试内容')
包的使用
第三方模块安装
工具:pip
使用:
pip -h/–help # 查看帮助
pip install 包名==版本 # 安装指定的包(可以指定版本)
pip install -r requirements.txt # 读取文件内容,根据内容进行安装
pip uninstall 包名 # 卸载指定的包
pip list # 查看已安装的包
pip show 包名 # 查看指定的包
pip freeze # 查看当前系统安装的包及版本
pip freeze > requirements.txt # 将系统环境冷冻
说明:
面向对象
面向对象
基础语法
类的定义
class 类名:
pass
使用说明:
定义类的关键字是class
类名:原则上符合标识符命名规范即可,但是通常都采用大驼峰风格命名,如:UserName
类名后不要忘记’:’
类的内容要进行整体缩进
属性可以通过变量体现,行为通过函数体现
成员访问:
示例:
class Person:
# 行为通过函数体现
# 吃饭
def eat(self):
print('毛氏红烧肉,听说很好吃!')
# 睡觉
def sleep(self):
print('喜欢睡觉也是生活态度!')
p = Person()
p.name = ‘ergou’
p.age = 22
print(p.name, p.age)
p.eat()
p.sleep()
self使用
class Person:
def run(self):
# self表示当前对象,就是调用该方法的对象
print(’{}每天以2m/s的速度奔跑5km’.format(self.name))
def introduce(self):
# 访问成员属性
print('我叫{},今年18岁'.format(self.name))
# 调用成员方法
# self的名字可以修改,但是通常都不改,调用方法时该参数不传
self.run()
lulu = Person()
lulu.name = '露露'
# lulu.run()
lulu.introduce()
yanbo = Person()
yanbo.name = '彦博'
# yanbo.run()
yanbo.introduce()
__str__方法
class Person:
# 打印对象时默认打印:类名+地址
# 重写该方法,打印对象时会打印该方法的返回值
# 该方法必须返回一个字符串
# 使用str方法强制类型转换时也会调用该方法
def str(self):
return ‘我是{},今年{}岁’.format(self.name, self.age)
p = Person()
p.name = '勒布朗.詹姆斯'
p.age = 34
print(p)
s = str(p)
print(s)
__init__方法
class Cat:
def str(self):
return ‘name:{},age:{},color:{}’.format(self.name, self.age, self.color)
# 构造方法:创建对象后会自动调用,可以进行初始化设置
def __init__(self, name, age, color):
# print('__init__')
self.name = name
self.age = age
self.color = color
# 这种方式比较繁琐
# jiafei = Cat()
# jiafei.name = '加菲'
# jiafei.age = 2
# jiafei.color = '橘黄色'
# print(jiafei)
jiafei = Cat('加菲', 2, '橘黄色')
print(jiafei)
__del__方法
class Pig:
# 析构方法:当对象释放时,系统会自动调用
# 该方法一般做资源释放操作,如:断开数据库连接、文件关闭
def del(self):
print(‘大师兄,我不行了’)
bajie = Pig()
del bajie
print('八戒,一路走好!')
思考:小明手里有两张牌,左手♥K,右手♠A,小明交换两手的牌后,手里分别是什么?
先找到对象:♥K、♠A、左手、右手、小明
根据对象抽象类:人、手、牌
设计相关的类,需要根据功能反复完善
# 牌的类
class Poker:
def __init__(self,color,number):
self.color = color
self.number = number
def __str__(self):
return '{}{}'.format(self.color,self.number)
#创建两张牌
p1 = Poker(‘♥’,‘K’)
p2 = Poker(‘♠’,‘A’)
#手的类
class Hand:
def init(self,poker=None):
self.poker = poker
def hold_poker(self,poker):
self.poker = poker
#创建两只手
left_hand = Hand(p1)
right_hand = Hand(p2)
#人的类
class Person:
def init(self,name,left_hand,right_hand):
self.name = name
self.left_hand = left_hand
self.right_hand = right_hand
#展示牌
def show(self):
print('{}张开手'.format(self.name),end=' ')
print('左手:{}'.format(self.left_hand.poker),end=' ')
print('右手:{}'.format(self.right_hand.poker))
#交换手中的牌
def swap(self):
self.left_hand.poker,self.right_hand.poker =self.right_hand.poker,self.left_hand.poker
print('{}交换手中的牌'.format(self.name))
#创建小明对象
xiaoming= Person(‘小明’,left_hand,right_hand)
#展示手中的牌
xiaoming.show()
#交换周中的牌
xiaoming.swap()
#展示手中的牌
xiaoming.show()
常用内置函数
内置函数:在类中,特定的时刻会自动触发的函数
init、del、str
setattr、getattr、delattr
class Person:
def init(self, name):
self.name = name
# print(‘初始化对象’)
# 当设置属性时会自动调用
def __setattr__(self, key, value):
# print(key, value)
self.__dict__[key] = value
# 当获取不存在的属性时会自动触发
def __getattr__(self, item):
if item == 'age':
return 18
else:
return '你猜'
# 销毁对象的指定属性时会自动触发
def __delattr__(self, item):
print(item, '属性即将销毁')
xiaoming = Person('小明')
# xiaoming.name = '小明'
print(xiaoming.age)
print(xiaoming.height)
print(xiaoming.__dict__)
del xiaoming.name
print('over')
setitem、getitem、delitem
class Person:
# 将对象当做字典操作,添加或设置属性时自动触发
def setitem(self, key, value):
# print(key, value)
self.dict[key] = value
# 将对象当做字典操作,根据键获取值时会自动触发
def __getitem__(self, item):
# print(item)
return self.__dict__.get(item)
# 将对象当做字典操作,根据键销毁属性时会自动触发
def __delitem__(self, key):
print(key, '属性即将销毁')
del self.__dict__[key]
xiaoming = Person()
# xiaoming.name = '小明'
# print(xiaoming.name)
xiaoming['name'] = '小明'
print(xiaoming['name'])
del xiaoming['name']
print(xiaoming['name'])
call
class Person:
# 将对象当做函数调用,该方法会自动触发
def call(self, *args, **kwargs):
# print(‘call’, args)
return sum(args)
p = Person()
# 将对象当做函数调用,必须重写类的call方法
ret = p(1, 2, 3)
print(ret)
def test():
pass
# 判断一个对象是否可以调用
print(callable(p))
print(callable(test))
# 判断一个对象是否是函数
from inspect import isfunction
print(isfunction(p))
print(isfunction(test))
# 判断对象是否拥有指定属性,若对象可以调用,那么一定拥有__call__属性
print(hasattr(p, '__call__'))
print(hasattr(test, '__call__'))
练习
设计学生和班级类
#学生类
class Student:
def __init__(self,name,num,age,score):
self.name = name
self.num = num
self.age = age
self.score = score
def __str__(self):
return '姓名:{} 学号:{} 年龄:{} 成绩:{} '.format(self.name,self.num,self.age,self.score)
#班级类
class Class:
def __init__(self,name):
self.name = name
#用于保存学生信息列表
self.stu_list = []
# 用于保存学生信息 便于快速查找
self.stu_dict = {}
#添加学生
def add_stu(self,stu):
self.stu_list.append(stu)
self.stu_dict[stu.num] = stu
#查看学生信息
def show(self):
for s in self.stu_list:
print(s)
#删除学生
def del_stu(self,num):
#从字典中删除
s = self.stu_dict.pop(num)
#从列表中删除
self.stu_list.remove(s)
#查找学生
def get_stu(self,num):
return self.stu_dict.get(num)
#学生排序
def sort_stu(self,key=None,reverse=False):
self.stu_list.sort(key=key,reverse=reverse)
#创建班级对象
c = Class('ZZ-PY1807')
from random import randint
for i in range(10):
name = 'stu'+str(i)
num = 100+i
age = randint(20,30)
score = randint(0,100)
#创建学生对象
stu = Student(name,num,age,score)
#添加到班级
c.add_stu(stu)
print(c.get_stu(101))
# c.sort_stu(key=lambda s:s.score,reverse=True)
# c.show()
将歌词解析封装成类,要求:通过一个根据时间戳返回歌词的方法
提示:歌词类、管理类
[ti:蓝莲花]
[ar:许巍]
[al:留声十年绝版青春北京演唱会]
[00:-01.70]蓝莲花
[00:-00.70]演唱:许巍
[00:00.00]
[00:00.70]没有什么能够阻挡
[00:06.01]你对自由的向往
[00:11.43]天马行空的生涯
[00:16.99]你的心了无牵挂
[00:21.20]
[02:11.55][01:50.60][00:22.63]穿过幽暗的岁月
[02:16.93][01:55.60][00:27.81]也曾感到彷徨
[02:22.21][02:01.09][00:33.13]当你低头的瞬间
[02:27.62][02:06.33][00:38.32]才发觉脚下的路
[02:31.64][02:10.23][00:42.37]
[02:32.97][00:43.79]心中那自由的世界
[02:38.23][00:49.50]如此的清澈高远
[02:43.30][00:54.31]盛开着永不凋零
[02:47.70][00:58.50]蓝莲花
[02:53.95][03:00.06][01:05.41]
import os
歌词类
class Lrc:
def __init__(self, sec, lrc):
self.sec = sec
self.lrc = lrc
def __str__(self):
return '{}:{}'.format(self.sec, self.lrc)
管理类
class LrcManager:
def __init__(self, lrc_file):
# 保存歌词信息
self.lrc_dict = {}
# 保存歌曲信息
self.song_dict = {}
# 时间信息列表
self.time_list = []
# 保存歌词文件
self.lrc_file = lrc_file
# 调用解析函数
self.jiexi()
def jiexi(self):
# 判断传递是否是歌词文件
if os.path.isfile(self.lrc_file):
fp = open(self.lrc_file, 'rb')
# 读取所有的内容
self.lrc_file = fp.read()
self.lrc_file = self.lrc_file.decode('utf-8')
# 按照换行进行切割
lrc_list = self.lrc_file.splitlines()
# 。。。
# 根据时间戳返回对应歌词
def get_lrc(self, sec):
for t in self.time_list:
if t < sec:
return self.lrc_dict[t]
return self.lrc_dict[self.time_list[-1]]
# 面向对象
### 面向对象三大特点
- 封装:既是对数据结构的封装,又是处理数据的方法的封装。
- 继承:强调的是父子类的关系
- 多态:不同对象调用相同的方法,有不同的响应。
### 类的继承
- 相关概念
- 继承:父类的属性和方法,子类可以直接拥有,称为继承。
- 派生:子类在父类的基础上衍生出新的特征(属性或行为),称为派生。
- 总结:其实他们是一回事,知识描述问题的角度不同(继承侧重相同点,派生侧重不同点)
- 继承语法
```python
# class Animal:
# 当没有写父类时,默认继承自object
class Animal(object):
def __init__(self, name):
self.name = name
def run(self):
print('小动物喜欢一天到晚跑个不停')
# 定义一个子类,继承自Animal
class Dog(Animal):
pass
d = Dog('旺财')
# 可以直接拥有父类的属性
print(d.name)
# 也拥有父类的行为
d.run()
派生示例
class Animal:
def run(self):
print(‘一天到晚跑个不停’)
class Cat(Animal):
def eat(self):
print('猫喜欢吃鱼')
c = Cat()
c.run()
# 添加的属性
c.name = '加菲'
print(c.name)
# 衍生的方法
c.eat()
方法重写
class Animal:
def run(self):
print(‘小动物喜欢到处跑’)
def eat(self):
print('小动物喜欢吃东西')
class Cat(Animal):
# 父类方法完全不合适,覆盖重写
def run(self):
print('猫喜欢走猫步')
# 父类的方法不够完善,需要添加完善
def eat(self):
# 保留父类方法的内容
# Animal.eat(self) # 不建议使用
# super(Cat, self).eat()
super().eat() # 推荐使用
# 添加完善的内容
print('猫喜欢吃鱼')
c = Cat()
c.eat()
c.run()
多继承:一个类可以有多个父类
class A:
def test(self):
print(‘in class A func test…’)
class B:
def test(self):
print('in class B func test...')
def eat(self):
print('in class B func eat ...')
class C(A, B):
def eat(self):
# 默认的方式找父类,跟不重写方法时的顺序是一样的,
# 按照书写的先后顺序,默认是写在前面的类的方法
# super().eat()
# 明确指定调用哪个父类的方法
B.eat(self)
c = C()
c.test()
c.eat()
权限管理
class Person:
def init(self, name, age):
self.name = name
# 定义私有属性
self.__age = age
def test(self):
# 私有属性和方法可以在类的内部使用
print(self.__age)
self.__hello()
# 定义私有方法
def __hello(self):
print('for test')
class Man(Person):
def show(self):
# 私有属性和方法在子类也不可以使用
print(self.__age)
p = Person('老王', 38)
print(p.name)
# 属性前添加连个下划线,类的外部不能使用
# print(p.__age)
# 默认在添加两个下划线的属性名前添加了'_类名'
# print(p.dict)
# 强烈建议不要这样使用
# print(p._Person__age)
p.test()
# p.__hello()
m = Man('小明', 18)
# m.show()
类属性
class Person:
# 类属性,属于整个类
# nation = ‘中国’
# 限制对象可以使用的属性,可以提高效率,节约存储空间
__slots__ = ('name', 'age', 'nation')
def __init__(self, name):
# 成员属性,属于某个对象
self.name = name
# 成员属性,当不存在会会试着找一下类属性
# self.nation = 'xxx'
def test(self):
pass
# 通过类名访问类属性
# print(Person.nation)
p = Person('王大花')
# 可以通过对象访问类属性,但是不建议
print(p.name)
# print(p.nation)
p.age = 20
# p.height = 180
# 特殊的类属性
# 类名字符串
print(Person.__name__)
# 父类组成的元组
print(Person.__bases__)
# 类相关的信息
print(Person.__dict__)
print(Person.__slots__)
类方法
说明
作用:
示例1:
class Person:
# 成员方法,通过对象进行调用
def eat(self):
print(‘红烧鸡腿我喜欢吃’)
# 类方法,通过类名进行调用
@classmethod
def test(cls):
# cls表示当前类
print(cls, '类方法')
# 创建对象
@classmethod
def create(cls):
obj = cls()
obj.age = 1
return obj
p = Person()
p.eat()
Person.test()
p2 = Person.create()
print(type(p2))
示例2:
class Number:
def init(self, num1, num2):
self.num1 = num1
self.num2 = num2
def add(self):
return self.num1 + self.num2
def sub(self):
return self.num1 - self.num2
def mul(self):
return self.num1 * self.num2
def div(self):
if self.num2 == 0:
return None
return self.num1 / self.num2
# 对外提供简单易用的接口
@classmethod
def pingfanghe(cls, num1, num2):
n1 = cls(num1, num1)
n12 = n1.mul()
n2 = cls(num2, num2)
n22 = n2.mul()
n3 = cls(n12, n22)
return n3.add()
print(Number.pingfanghe(3, 4))
静态方法
说明:
示例:
class Person:
# 静态方法:没有cls参数
@staticmethod
def test():
print(‘static method test …’)
# 静态方法:可以创建对象
@staticmethod
def create():
p = Person()
p.age = 1
return p
Person.test()
p = Person.create()
print(type(p))
总结:
多态特性
定义:不同的对象,调用相同的方法,会有不同的响应
示例:
class Animal:
def run(self):
print(‘小动物走道都不一样’)
class Cat(Animal):
def run(self):
print('猫都的是猫步')
class Dog(Animal):
def run(self):
print('狗一般都走S型')
def func(obj):
obj.run()
func(Cat())
func(Dog())
属性函数
说明:可以将成员方法当做属性一样访问
作用:获取时以及设置指定属性时都可以进行人为干预,可以保护特定属性
示例:
class User:
def init(self, username, password):
self.username = username
self.__password = password
# 可以将方法像访问属性一样访问
@property
def test(self):
return 'hello'
# 保护指定的属性
@property
def password(self):
print('大哥,有人想偷看密码')
return '哈哈,让你偷看,没门'
# 在设置对应属性时会自动调用
@password.setter
def password(self, password):
print('密码设置', password)
# 人为干预密码的设置过程,如:加密存储密码
self.__password = 'xxx' + password + 'yyy'
u = User('大狗', '123456')
# u.test()
# print(u.test)
print(u.password)
u.password = '654321'
print(u.__dict__)
虚拟环境
面向对象
抽象基类(了解)
说明:
示例:
from abc import ABC, abstractmethod
# 抽象基类
class Animal(ABC):
# 定义抽象方法:规定接口
@abstractmethod
def run(self):
pass
# 抽象基类无法实例化
# a = Animal()
class Cat(Animal):
# 子类中必须实现抽象基类的抽象方法,才能实例化
def run(self):
print('猫喜欢走猫步')
c = Cat()
特殊函数
示例1
d = {‘name’: ‘xiaoming’, ‘age’: 20}
# 返回对象的字符串表示形式
r = repr(d)
print(r, type(r))
# 执行有效的python代码字符串
d2 = eval(r)
print(d2, type(d2))
a = 10
b = 20
c = eval('a + b')
print(c)
示例2:
class Person:
def init(self, name, age):
self.name = name
self.age = age
# print打印对象,str方法转换时都会触发
def __str__(self):
print('__str__')
return '姓名:{} 年龄:{}'.format(self.name, self.age)
# 返回对象的字符串表示形式,使用repr函数处理时会自动触发
def __repr__(self):
return "Person('{}', {})".format(self.name, self.age)
p = Person('王大花', 18)
# print(p)
# s = str(p)
r = repr(p)
print(r)
p2 = eval(r)
print(p2, type(p2))
内置方法
构造和析构
init、del__
干预属性操作
setattr、getattr、delattr
支持字典操作
setitem、getitem、delitem
对象支持函数调用
call
打印输出或str转换
str
对象的字符串表示,调用repr方法时触发
repr
运算符重载
算术运算符
示例:
class Number:
def init(self, num):
self.num = num
# 对象出现在'+'的左边时会自动触发
def __add__(self, other):
print('__add__')
return self.num + other
# 对象出现在'+'的右边时会自动触发
def __radd__(self, other):
print('__radd__')
return self.num + other
# +=运算时自动触发,若没有实现会调用__add__
def __iadd__(self, other):
print('__iadd__')
# 返回新的Number对象
# return Number(self.num + other)
# 返回处理后的原始对象
self.num += other
return self
n = Number(10)
print(id(n))
n += 50 # n = n + 50
print(id(n))
自行测试
加法:add、radd、iadd
减法:sub、rsub、isub
乘法:mul、rmul、imul
除法:truediv、rtruediv、itruediv
求余:mod、rmod、imod
关系运算符
class Number:
def init(self, num):
self.num = num
# 大于 >
def __gt__(self, other):
print('__gt__')
return self.num > other
# 小于 <
def __lt__(self, other):
print('__lt__')
return self.num < other
# 等于 ==, 判断是否相等,当不实现__ne__时,!=运算也会触发
def __eq__(self, other):
print('__eq__')
return self.num == other
# 大于等于 >=
def __ge__(self, other):
print('__ge__')
return self.num >= other
# 小于等于 <=
def __le__(self, other):
print('__le__')
return self.num <= other
# 不等于 !=
def __ne__(self, other):
print('__ne__')
return self.num != other
n = Number(20)
print(n > 10)
print(n < 10)
print(n == 10)
print(n != 10)
内存管理
引用计数
python中所有的数据都是通过类来实现的,对象的管理是通过引用计数实现的
当创建一个对象赋值给一个变量时,引用计数为1,当多一个变量指向该对象时,计数值加1;当少一个变量指向对象时,计数值减1。计数值减到0时会调用__del__方法释放存储空间
不可变变量引用计数是没有意义的
示例:
import sys
# 不可变变量的引用计数没有意义
a = 10
print(sys.getrefcount(a))
lt = [1, 2, 3]
lt2 = lt
# 本身此时引用计数为1,但是该方法也引用了一次
print(sys.getrefcount(lt))
del lt2
print(sys.getrefcount(lt))
class Person:
def del(self):
print(‘对象即将释放’)
p = Person()
print(sys.getrefcount§)
del p
print(‘over’)
函数传参
对不可变变量来说,传递的是值,函数中不可能改变传递的参数
对于可变变量及自定义的类创建的对象,传递的是引用,函数中可以操作原对象
示例:
def test(a):
a += 1
num = 100
test(num)
print(num)
def test2(lt):
lt[0] = 10
lt = [1, 2, 3]
test2(lt)
print(lt)
深浅拷贝
import copy
lt = [1, 2, [3, 4]]
# 赋值会增加一个引用,访问的都是同一数据
lt2 = lt
# 浅拷贝:只拷贝对象本身,里面的元素只会增加一个引用
# lt2 = lt.copy()
# 专门的拷贝函数,也是浅拷贝,等价于上面的拷贝
lt2 = copy.copy(lt)
# 深拷贝:拷贝对象本身,对象中的元素也进行拷贝
# lt2 = copy.deepcopy(lt)
lt[0] = 100
lt2 = 30
print(lt)
print(lt2)
print(id(lt))
print(id(lt2))
# 判断是否是同一对象的多个引用
print(lt is lt2)
数据持久化存储
说明:持久化存储方案,普通文件、数据库、序列化
示例:
import pickle
class Person:
def __init__(self, name, age):
self.name = name
self.age = age
def __str__(self):
return 'name:{} age:{}'.format(self.name, self.age)
xiaoming = Person('xiaoming', 20)
# print(xiaoming)
# 序列化:会将对象转换为bytes
# s = pickle.dumps(xiaoming)
# print(s)
# 反序列化:从bytes中解析出对象
# xm = pickle.loads(s)
# print(xm, type(xm))
# 直接保存到文件
# fp = open('data.txt', 'wb')
# pickle.dump(xiaoming, fp)
# fp.close()
# 从文件中读取对象
fp = open('data.txt', 'rb')
xm = pickle.load(fp)
print(xm, type(xm))
异常处理
相关概念
异常处理
说明:异常处理可以理解为特殊的流程控制语句,可以提高代码的健壮性。
语法:
try:
print(‘正常代码’)
a = 3 / 0
print(‘执行结束’)
except Exception as e:
# 捕获异常,可以做出异常处理
print(‘出现异常’, e)
print('OVER')
多异常处理:
# try:
# # print(a)
# # a = 3/0
# d = {}
# print(d[‘name’])
# except NameError as e:
# print(‘NameError:’, e)
# except ZeroDivisionError as e:
# print(‘ZeroDivisionError:’, e)
# except Exception as e:
# print(‘Othre error:’, e)
try:
# print(a)
# a = 3 / 0
d = [1, 2, 3]
print(d[4])
except (NameError, ZeroDivisionError) as e:
# 将某些异常放在一起进行统一处理
print('name or zero:', e)
except Exception as e:
print('其他异常')
完整写法
try:
print(‘正常代码’)
print(a)
except Exception as e:
print(‘出现异常’, e)
else:
# 没有异常时会执行
print(‘正常结束’)
finally:
# 无论有无异常都会执行
print(‘最后执行’)
print('OVER')
手动抛出异常
try:
print(‘正常执行’)
# 根据业务逻辑分析,手动抛出异常
raise Exception(‘手动抛出的异常’)
print(‘执行结束’)
except Exception as e:
print(‘出现异常:’, e)
print('OVER')
异常嵌套
print(‘我要去上班,什么事也阻止不了我上班的脚步’)
try:
print(‘我准备骑电动车去上班’)
raise Exception(‘不知道那个缺德的家伙把我充电器拔掉了’)
print(‘骑电动车提前到达公司’)
except Exception as e:
print(‘电车异常:’, e)
try:
print(‘我准备坐公交去上班’)
raise Exception(‘等了20分钟没有公交车,果断放弃’)
print(‘乘坐公交准时到达公司’)
except Exception as e:
print(‘公交异常:’, e)
print(‘我准备打车去公司’)
print(‘打车还是快,还是能够提前到达公司’)
print('热情饱满的开始一天的工作')
自定义异常类
# 自定义异常类
class MyException(Exception):
def init(self, msg):
self.msg = msg
def __str__(self):
return 'MyException:' + self.msg
# 异常处理函数
def deal(self):
print('按照特定的方案处理异常')
try:
print('正常运行')
raise MyException('自定义异常')
except MyException as e:
print(e)
# 特定的处理方案
e.deal()
except Exception as e:
print('Exception', e)
print('OVER')
特殊场景
当进行文件操作时,无论过程是否出现异常,最后一定要关闭文件
使用with语句,保证文件关闭,无论中间是否出现异常
示例:
‘’’
fp = open(‘xx.txt’, ‘r’)
content = fp.read(1024)
print(content)
fp.close()
‘’’
with open(‘00-text.txt’, ‘r’) as fp:
content = fp.read(1024)
# …
# 结束时不需要考虑文件的关闭问题
# 无论中间是否出现了异常,一定会确保文件关闭
邮件与短信
邮件发送
简介:
用途:网站注册激活、通知、找回密码、营销等
库:smtplib
示例:
import os
import smtplib
from email.mime.text import MIMEText
# 邮件服务器
mail_server = 'smtp.1000phone.com'
# 用户名
mail_username = '[email protected]'
# 密码,通过环境变量获取,可以避免隐私信息的暴露
# 或授权码,QQ邮箱需要使用授权码
mail_password = os.getenv('MAIL_PASSWORD', '123456')
# 邮件内容
content = '请点击右边链接已完成激活'
# 创建用于发送的邮件消息对象
# 参数1:邮件内容
# 参数2:内容类型,plain表示普通文本,html表示网页
message = MIMEText(content)
# 设置主题
message['Subject'] = '账户激活'
# 设置发送者
message['From'] = mail_username
# 创建用于发送邮件的对象
# SMTP:邮件不加密,端口25
# SMTP_SSL:邮件加密传输,端口465,QQ邮箱必须使用加密
mail = smtplib.SMTP(mail_server)
# 身份认证
mail.login(mail_username, mail_password)
# 发送给谁
to = '[email protected]'
# 发送邮件
mail.sendmail(mail_username, to, message.as_string())
# 结束
mail.quit()
说明:
QQ邮件发送特别提醒:
预备知识
http.client:可以发送http请求
import http.client
# 创建对象(相当于一个浏览器)
connect = http.client.HTTPConnection('www.baidu.com')
# 发送请求
connect.request(method='GET', url='http://www.baidu.com')
# 获取响应
resp = connect.getresponse()
# 打印响应的内容
print(resp.read().decode('utf-8'))
json和XML
说明:使用非常广泛的数据传输格式,现在JSON使用居多
JSON使用:
import json
d = {‘name’: ‘xiaoming’, ‘age’: 18}
s = json.dumps(d)
print(s, type(s))
d2 = json.loads(s)
print(d2, type(d2))
urllib.parse
from urllib.parse import urlencode, urlparse, parse_qs
d = {'name': 'xiaoming', 'age': 18}
# name=xiaoming&age=18
# 将字典数据进行URL编码
print(urlencode(d))
url = 'https://www.baidu.com/s?ie=utf-8&f=8&rsv_bp=0&rsv_idx=1&tn=baidu&wd=python&rsv_pq=df80f3db0000abd0&rsv_t=a542qF5GDdQDk6bhs2c3yr7BGToMf0ge1e2b%2BnpWm0lY4ZV8ICYY1yM48FI&rqlang=cn&rsv_enter=1&rsv_sug3=6&rsv_sug1=6&rsv_sug7=101'
# 解析URL
p = urlparse(url)
# 提取请求字符串
print(p.query)
query_str = 'like=sport&like=music&like=games&name=ergou'
# 解析请求字符串:将请求字符串转换为字典
# d2 = parse_qs(p.query)
d2 = parse_qs(query_str)
print(d2)
短信发送
说明:注册登录验证码、通知消息、营销短信、面向接口的开发等。
平台:阿里、秒嘀、云之讯、…
认识:云之讯(www.ucpaas.com)
示例:
# 账户sid
sid = ‘b5c6fd1d02071a766009475f0478e0ac’
# 认证令牌
token = '2426bff7df8ff95f59fcbcdce3362c58'
# 应用ID
appid = 'fac78e7f7f0647c7a47c4809ff564f5c'
# 模板ID
templateid = '29735'
# 参数
param = 'stu.1000phone.net,123456,5'
# 接收手机号
mobile = '18134411879'
# 参数字典
data = {
"sid": sid,
"token": token,
"appid": appid,
"templateid": templateid,
"param": param,
"mobile": mobile,
}
# 将字典转换为JSON字符串
import json
json_data = json.dumps(data)
# print(json_data)
# 创建'浏览器'对象
import http.client
connect = http.client.HTTPConnection('open.ucpaas.com')
# 接口地址
url = 'https://open.ucpaas.com/ol/sms/sendsms'
# 请求头
header = {
'Accept': 'application/json',
'Content-Type': 'application/json;charset=utf-8',
}
# 发送请求
connect.request(method='POST', url=url, body=json_data, headers=header)
# 获取响应
resp = connect.getresponse()
# 打印响应内容
print(resp.read().decode('utf-8'))
练习 见第四周第一天代码
邮件短信发送都需要封装成函数
终端银行系统
正则表达式
应用场景
使用原则
基本使用
match:只从开头进行匹配,匹配到就返回结果对象,没有找到返回None
search:从任意位置匹配,功能同上,都是单次匹配(找到就停)
m = re.search(‘abc’, ‘hadajabcadjlae’)
if m:
# 返回匹配的内容
print(m.group())
# 返回匹配内容的位置
print(m.span())
findall:全部匹配,返回所有匹配到的结果列表,没有找到返回空列表
f = re.findall(‘abcd’, ‘abcasjdlaabcaksjd;abcasdjla’)
print(f)
compile:创建正则表达式对象,可以让创建正则对象和内容匹配分开操作
c = re.compile(‘cba’)
m = c.search(‘casdhaj;acbaalsdk’)
if m:
print(m.group())
f = c.findall(‘ahkjdcbasdkjalcbasakldjacba’)
print(f)
此方式可以分开操作,比较灵活
正则语法
单个字符
普通字符:简单理解就是一对一的完全匹配
[]:中间的任意一个字符
[abc]:abc的任意一个字符
[0-9]:任意的数字字符
[a-zA-Z]:任意的字母
[^0-9]:非数字字符
. :除’\n’以外的任意字符
\d:数字字符,等价于[0-9]
\D:非数字字符,等价于[^0-9]
\w:匹配字(数字、字母、下划线)
\W:匹配非字(\w相反的内容)
\s:空白字符(\n、\r、\t、空格)
\S:非空白字符(\s相反的内容)
\b:词边界(开头、结尾、空格、标点)
\B:非词边界(\b相反的内容)
次数限定:修饰前面的单个字符出现的次数
*:任意次
+:至少一次
?:至多一次
{m}:指定m次
{m,n}:m <= 次数 <=n
{m,}:至少m次
{,m}:至多m次
边界限定
^:以指定的内容开头
$:以指定的内容结尾
示例:
import re
f = re.findall(‘world$’, ‘asjdhelloaskworld’)
f = re.findall(’^\w*$’, ‘asjdhelloaskworld’)
print(f)
优先级与整体
import re
# |:表示或,拥有最低的优先级
# ():可以表示一个整体
s = re.search('hell(o|w)orld', 'akdhahellworld')
if s:
print(s.group())
分组匹配
示例1:
import re
c = re.compile(’(\d+)([a-z]+)(\d+)’)
s = c.search(‘agaj123sdgewsgdf456adjsd’)
if s:
# 0:表示完整匹配内容,之后的数字表示第几组,也就是第几个()匹配的内容
print(s.group(0), s.span(0)) #123sdgewsgdf456 (5, 20)
print(s.group(1), s.span(1)) #123 (5, 8)
print(s.group(2), s.span(2)) #sdgewsgdf (8, 17)
print(s.group(3), s.span(3)) # 456 (17, 20)
示例2:
import re
c = re.compile(r’<(?P[a-z]+)><(?P[a-z]+)>\w+(?P=two)>(?P=one)>’)
s = c.search(‘
if s:
print(s.group())
# 返回所有组的信息,是一个元组
print(s.groups())
# 返回分组的字典,键是组的名字,值时匹配的内容
print(s.groupdict())
findall
import re
# 按照正则进行匹配,但是添加()后,结果只显示()匹配的内容
f = re.findall('A(abc)A', 'asdjAabcAasdjAabcAsdkabca')
print(f)
贪婪匹配
贪婪:最大限度的匹配。正则的匹配默认是贪婪的
非贪婪:只要满足条件,能少匹配就少匹配。可以使用’?'取消贪婪
示例:
import re
c = re.compile(‘a.*?b’)
s = c.search(‘sdhaasdajasksdbsdjbsdk’)
if s:
print(s.group())
匹配模式
说明:匹配模式就是对默认的匹配原则进行整体的修饰
示例:
import re
s = re.search(r’^hello’, ‘asdkasj\nhelloajsdhkas’, re.M)
string = ‘’’
if s:
print(s.group())
字符转义
匹配凡是跟正则语法相关的字符都需要需要进转义
示例:
import re
c = re.compile(r’\d’)
s = c.search(’\d’)
if s:
print(s.group())
c = re.compile(r’\b’)
s = c.search(r’\b’)
if s:
print(‘成功’, s.group())
在定义字符串的开头添加’r’表示原始字符串,可以轻松解决很多关于转义的问题
正则切割
import re
c = re.compile(r'\d')
string = '正则其实不难1但是学完之后2发现什么也不出来3是这样吧'
# 字符串是固定切割,不能解决某类的匹配切割问题
# print(string.split('1'))
# 按照正则进行切割
ret = c.split(string)
print(ret)
# 整体方案
print(re.split(r'\d', string))
正则替换
string = ‘helloadjasdhelloskdjalkhellosdjka’
# 字符串替换
new_string = string.replace(‘hello’, ‘world’, 2)
print(new_string)
import re
s = 'how1are2you'
# 正则替换
# s2 = re.sub(r'\d', ' ', s)
# 替换时可以传递一个函数,使用函数的返回值进行替换
def double(s):
return str(int(s.group()) * 2)
# return 'xxx'
# 使用专门的处理函数,可以人为的干预替换过程
s2 = re.sub(r'\d', double, s)
print(s2)
练习
匹配手机号
'''import re
ret = re.compile(r'1[3-9]+\d{9}')
s = ret.search('dgads18939472276')
if s:
print('是手机号',s.group())'''
匹配邮箱
'''import re
ret = re.compile(r'1[3-9]+\d{9}')
s = ret.search('dgads18939472276')
if s:
print('是手机号',s.group())'''
匹配URL
import re
c = re.compile(r'https?:\/\/([0-9a-zA-Z]+\.)+[a-zA-Z]+(:\d+)?[/a-zA-Z0-9\._]+(\?.*)?')
url = 'https://www.baidu.com:443/s/a/b/index.html?ie=utf-8&f=8'
a = c.search(url)
if a:
print(a.group())
'''
匹配IP
import re
c = re.compile(r'(((25[0-5]|2[0-4]\d{2})|([1-9]?\d))\.){3}((25[0-5]|2[0-4]\d{2})|([1-9]?\d))')
ipv4 = '0.0.0.0'
ipv4 = '255.255.255.0'
s = c.search(ipv4)
if s:
print(s.group())
网络编程
相关概念
范围:0~65535
公认端口:0~1023
http: 80
https: 443
smtp: 25
ftp: 21
ssh: 22
其他端口:1024~65535
TCP协议
UDP协议
mini-web服务器
基础总结
多进程WEB服务器
图片处理
说明:通常对于图片的操作有这些操作(缩放、旋转、翻转、裁剪、滤镜、画图等)
扩展库:PIL,只支持PY2,在PY3中使用需要安装pillow库
安装:pip install pillow
预备知识:
缩放操作
from PIL import Image
# 打开图片
img = Image.open('erha.jpg')
# 修改尺寸,在原图上修改
# img.thumbnail((200, 300))
# 修改尺寸,返回新的对象
img.resize((200, 200)).show()
# 展示图片
# img.show()
# 保存图片,指定文件名(要带后缀)
# img.save('erha200_300.jpg')
画图操作
from PIL import Image, ImageDraw, ImageFont
# 新建图片
img = Image.new('RGB', (300, 300), 'red')
# 创建画笔
draw = ImageDraw.Draw(img)
# 画点(一个像素)
draw.point((150, 150), fill=(0, 255, 0))
# 画线
draw.line(((0, 0), (100, 100)), fill=(0, 0, 255), width=5)
# 创建字体对象
font = ImageFont.truetype('xdxwz.ttf', 30)
# 画字
draw.text((200, 200), 'A', fill=(255, 255, 0), font=font)
img.show()
画验证码
from PIL import Image, ImageDraw, ImageFont, ImageFilter
from random import randint
def rand_color(is_light=False):
if is_light:
return (randint(128, 255), randint(128, 255), randint(128, 255))
return (randint(0, 127), randint(0, 127), randint(0, 127))
def rand_string(length=4):
code = ''
for i in range(length):
code += str(randint(0, 9))
return code
# 获取一个浅色背景
back_color = rand_color(is_light=True)
# 创建图片
img = Image.new('RGB', (200, 50), back_color)
# 创建字体
font = ImageFont.truetype('xdxwz.ttf', 30)
# 创建画笔
draw = ImageDraw.Draw(img)
# 生成随机验证码
code = rand_string()
# 画字符
for i in range(len(code)):
draw.text((15+50*i, -5), code[i], font=font, fill='black')
# 画干扰点
for i in range(5000):
x = randint(0, 200)
y = randint(0, 50)
draw.point((x, y), fill=rand_color())
# 添加滤镜,会生成新的图片对象
# img = img.filter(ImageFilter.GaussianBlur)
# 展示
img.show()
PY2与PY3的区别
简单的数据结构
排列组合
import itertools
# 排列:从m个元素中去n个元素,所有的可能就是排列(有序)
# 当m等于n时称为全排列
# it = itertools.permutations([1, 2, 3], 3)
# 组合:没有顺序的排列
# it = itertools.combinations([1, 2, 3, 4], 2)
# 笛卡尔成绩:多个序列中的组合
# it = itertools.product([1, 2], [3, 4], [5, 6])
# 序列一样的情况
it = itertools.product([1, 2], repeat=3)
# 与上式等价
# it = itertools.product([1, 2], [1, 2], [1, 2])
for i in it:
print(i)
计数器与队列
from collections import Counter, deque
c = Counter([1, 2, 3, 4, 2, 1, 2, 1, 3, 4, 2])
print(c)
# 转换为字典
print(dict(c))
# 获取出现次数最多的元素及次数
print(c.most_common(1))
# 双向队列
d = deque([1, 2, 3])
# 从右侧添加
d.append(4)
# 从左侧实现
d.appendleft(5)
# 从右侧弹出元素
print(d.pop())
# 从左侧弹出元素
print(d.popleft())
# 从右边扩充序列
d.extend([7, 8, 9])
# 从左侧扩充序列
d.extendleft(['a', 'b', 'c'])
# 循环移动:正数表示右移,负数表示左移
# d.rotate(1)
d.rotate(-1)
print(d)
print(list(d))
链表