Pyhton学习的基础
函数->功能, 如print(),input(),range(),
方法->功能, 如index()(尽量不用此方法),find(),
类里面的函数就叫做方法
容器->列表,字符串,元组,字典,set集合.
模块-是可以调用的
appearance->通用的意思
标识符 ->变量,函数,类,文件等的名字
def->定义(define)
百分比转换 print("%.2f %%"(变量名 * 100))
import 导入
类中的方法-->行为,功能
-------------------------------------------------------------------------------------------------------
学习方法
总结知识点 写,分析代码
将知识点引用到作业
至少2遍作业
-------------------------------------------------------------------------------------------------------
计算机
内存 随机存储器,电信号表示数据(电路的状态)读写速度快,只读存储器 主板上的半导体,开机时的数据
硬盘使用磁表示数据,之所以慢是因为多一步转换过程
-------------------------------------------------------------------------------------------------------
驱动程序由硬件厂商开发
os通过驱动程序来管理软硬件资源
-------------------------------------------------------------------------------------------------------
计算机只能识别和执行01的机器指令(机器语言(二进制数据))内存里的数据既是01
语言处理程序=编译器(如python解释器)将程序翻译为01的机器语言让计算机可以识别执行
将软件读取到内存——将文件读取到内存——cpu中的控制器调用声卡显卡驱动——驱动程序调用硬件处理数据
-------------------------------------------------------------------------------------------------------
编程语言->人与计算机交流的语言
刘峰说了Python是世界上最牛逼的语言
-------------------------------------------------------------------------------------------------------
Python的缩进很需要注意
-------------------------------------------------------------------------------------------------------
Python特点
-标准库功能强大,
框架确立,将功能添加到程序中,
-语法优美,简单,易学,免费,开源
-扩展性强
-缩进以至于整洁优美规范
-------------------------------------------------------------------------------------------------------
Python的缺点
执行效率比较慢,更适用于高性能计算机
-------------------------------------------------------------------------------------------------------
Python学习方向
web开发
操作系统管理,服务器运维的自动化脚本
网络爬虫
大数据挖掘分析,科学计算(人工智能)
桌面软件
服务器软件
游戏
-------------------------------------------------------------------------------------------------------
Python解释器
将程序转换为01机器可执行的数据
给Python提供丰富的类库使python更加强大
可以提高开发效率
-------------------------------------------------------------------------------------------------------
Pycharm
create Project用来创捷一个存放代码文件的文件夹
version control版本控制工具 整合代码
pure python 纯python工程
-------------------------------------------------------------------------------------------------------
输入法中文时使用英文标点(实用技巧)
一个语句一行,行为单位
-------------------------------------------------------------------------------------------------------
注释的分类
注释最好加在上边
单行注释-注释的文字只能在同一行,不能写成多行 # 开头
快捷键 选中注释掉的行 CTRL+/(左斜线,句号后边)
-------------------------------------------------------------------------------------------------------
多行注释-使用三对引号引中注释文字(单双引号都可以)
使用双引号时不能嵌套
-------------------------------------------------------------------------------------------------------
什么时候添加注释
开发的功能比较复杂时
开发的功能是核心功能
-------------------------------------------------------------------------------------------------------
变量-就是内存中的一块区域
数据读取到内存后使用变量临时存储,
在程序中给变量起个别名即为变量名,通过变量名来使用变
定义变量的格式-->变量名=数据值 =是赋值,数据值赋值给变量名
不是第一给变量赋值,表示修改变量值
-------------------------------------------------------------------------------------------------------
变量以及类型
数据分类-根据数据的计算规则对数据进行分类
整数-int 小数-float 字符串-str使用引号引起来的内容 布尔类型-bool(ean)只有两个数据值True,False
列表-list 元组tuple 字典-dict set集合-set
-------------------------------------------------------------------------------------------------------
定义变量时不需要指定变量类型python解释器会自动推导
查看数据类型 type(数据)
-------------------------------------------------------------------------------------------------------
标识符的命名规则
1.字母,下划线,数字组成,不能以数字开头,不能是关键字(在python中事先预留出来的单词,已有特殊含义)import keyword-keyword.kwlist然后打印出来
2.必须见名知意
3.下划线连接单词,都是小写
-------------------------------------------------------------------------------------------------------
print()打印出来在控制台里面
-------------------------------------------------------------------------------------------------------
格式化操作符
如果输出的内容有相应的类型,先用格式化操作符占位,然后再替换
string->%s
整数->%d
保留几位数字 %nd (n+d是总位数)
float类型保留小数位数- %.nf(n就是要保留的位数)
-------------------------------------------------------------------------------------------------------
如果输出的字符串中包含多个变量值,用小括号括住变量,使用逗号隔开,且顺序必须对应
print(" xxx%s ,xxx%d" % (a,b) )
输出一个%是 "%% %d"
-------------------------------------------------------------------------------------------------------
使用float()等 对input()录入的string类型的数据进行数据转换
-------------------------------------------------------------------------------------------------------
算术运算符
% 取余,取模
// 取整,舍去余数
** 取幂
-------------------------------------------------------------------------------------------------------
字符串与整数只能相乘,不能做其他操作,字符串的倍数.
字符串与字符串相加表示 连接两个字符串
-------------------------------------------------------------------------------------------------------
数据类型转换
使用float()对input()录入的string类型的数据进行数据转换
-------------------------------------------------------------------------------------------------------
复合赋值运算符
+= 左边的变量与右边的数据相加再赋值给左边的变量
-------------------------------------------------------------------------------------------------------
输入
input()在控制台录入数据,在程序中得到该数据
得到的数据是一定是字符串
-------------------------------------------------------------------------------------------------------
数据类型转换
格式: 目标数据类型(数据) 如a=9--> int(a),str(b)
bool类型非零都为True,0为False
str(9.0)无法转换为int类型
-------------------------------------------------------------------------------------------------------
Debug调试程序
在怀疑出错的位置添加断点
以debug方式运行程序
在debugger中点击向下的箭头逐行测试
点击向上的箭头执行两个断电之间的所有行
-------------------------------------------------------------------------------------------------------
关系运算符的结果是bool类型,结果要么是True要么是False
-------------------------------------------------------------------------------------------------------
关系运算符中==是判断是否相等
-------------------------------------------------------------------------------------------------------
if条件语句的格式
if关系表达式:
语句体
语句体可以是一行
也可以是多行
-------------------------------------------------------------------------------------------------------
执行流程:
if..else..
if关系表达式:
语句体1-->(条件满足关系表达式,就执行这个)
else:
语句体2-->(条件不满足关系表达式就执行这个)
-------------------------------------------------------------------------------------------------------
if...elif...else...-->适合用于判断3种及以上条件
if 条件判断语句1:
语句体1
elif 条件判断语句2:
语句体2
...
else
语句体 n+1
-------------------------------------------------------------------------------------------------------
三目运算(用来简化 if....else..语句)
a if a>b else b
如果(a>b)的条件成立,结果是a,否则就是b(a,b是值!)
关系表达式后面这个地方一定要注意 : (冒号)
-------------------------------------------------------------------------------------------------------
逻辑运算符
结果是bool类型
and 和 两边的条件都满足为True
or 或 两边条件有一个满足为True
not 非 取相反
-------------------------------------------------------------------------------------------------------
获得随机数
导入工具包(一般写在程序的最上边)
调用工具包里的功能,获得一个随机数
random.randint(始,终)
-------------------------------------------------------------------------------------------------------
break 中断循环,不再执行循环!
continue 结束本次循环,继续下次循环(在while循环使用continue时需要使计数器避免死循环!!!)
只对所在的的循环起作用,不对外面的循环起作用
-------------------------------------------------------------------------------------------------------
while循环语法格式
定义变量并赋值 1
while 条件判断语句: 2
重复执行的代码语句 3
修改条件的语句 4 执行流程 1-->2-->3-->4 -->2-->3--4 -->2-->3-->4--
如果2的值为 False 时,循环结束(条件判断语句不成立时,循环结束)
while循环嵌套时在内循环里要重新定义计数器
-------------------------------------------------------------------------------------------------------
\n 换行符 \t制表符(一个缩进) \\目录分割符(如:path= "D:\\视频\\123.flv")
-------------------------------------------------------------------------------------------------------
for循环语法格式
for 变量 in range() 或者 可迭代的容器:
重复执行的代码块
-------------------------------------------------------------------------------------------------------
range() 可以得到 一个 数据区间
range(开始数字,结束数字)!!!不包含结束的数字
如[1,2,3,4,5]==range(1,6)
-------------------------------------------------------------------------------------------------------
流程判断语句
顺序结构语句(从上往下按顺序执行的语句)
判断语句
循环语句
-------------------------------------------------------------------------------------------------------
字符串:
使用一对单引号或者一对双引号或者三队单引号引住的任何内容都是字符串
索引的作用
1.可以根据索引查找某个元素
2.根据索引截取字符串
-------------------------------------------------------------------------------------------------------
遍历
一个一个地得到
-------------------------------------------------------------------------------------------------------
切片
就是截取一段(截取索引超出范围表示截取到最后一个元素)
-------------------------------------------------------------------------------------------------------
列表中的元素可以是任何类型的
定义列表的格式
列表名 =["元素1","元素2".....](方括号!!)
-------------------------------------------------------------------------------------------------------
增加列表元素的方法
append()
列表1.extend(列表2) 将列表2 的内容添加到列表1的后面,元素可以重复
-------------------------------------------------------------------------------------------------------
修改列表元素的方法
列表名[索引]=新的元素值
-------------------------------------------------------------------------------------------------------
删除列表中的元素
列表名.remove("元素")如果 这个元素在列表中不存在会报错
列表名.pop()默认删除列表中最后一个元素
列表名.pop(索引)删除指定索引值的元素
列表名.clear()清空列表
-------------------------------------------------------------------------------------------------------
列表的排序
列表内的元素需要是同一类型的数据,不同类型无法排序
列表名.sort()默认按照升序排序
列表名.sort(reverse=True)按照倒序排序
-------------------------------------------------------------------------------------------------------
列表推导式:
定义列表并向列表中添加数据的简化代码
x 是 从容器中遍历出来的数据,for 前面的数据添加到列表中
列表名 = [x for x in 可迭代的函数或者range()函数]
加if条件判断语句
列表名 = [x for x in 可迭代的函数或者range()函数 if 条件判断语句]
遍历出来的数据满足条件判断语句才将数据添加到列表中
-------------------------------------------------------------------------------------------------------
Tuple
元组就是一个不能修改的列表
格式:
元组名=("元素1","元素2",....)(小括号!!!)
只有一个元素的元组
元组名=(元素1,)没有,的的话就不是元组
-------------------------------------------------------------------------------------------------------
字典也是一个容器
数据时成对出现时就使用字典来存储
key 是不可以修改的!!
key是唯一的,不可重复!!
-------------------------------------------------------------------------------------------------------
格式:
字典名 = {"key1: value1","key2: value2", ....}
-------------------------------------------------------------------------------------------------------
存储数据时一存一对,查询时的效率高
-------------------------------------------------------------------------------------------------------
要想得到值必须通过键来查找--> 字典名["key"]是其value,key不存在的话会报错
-->字典名.get(key)查找 空的key并不会报错尽量使用此方法
-------------------------------------------------------------------------------------------------------
修改value需要通过key来修改
字典名[key]=新的value
-------------------------------------------------------------------------------------------------------
添加一个键值对
字典名["key"]="value"
这个key必须是字典中尚未存在
-------------------------------------------------------------------------------------------------------
删除一个键值对
字典名.pop(key)-->删除key对应的键值对
字典名.popitem()-->删除最后一个键值对
字典名.clear()-->清空字典里的键值对
-------------------------------------------------------------------------------------------------------
字典中键值对的key不能是列表或者字典,这两个是可变类型的,关键字key不能变,变了就不是这个keyle
-------------------------------------------------------------------------------------------------------
字典的遍历
方式1 先得到所有的key对应的列表 字典名.keys()得到一个列表,定义为key_list
遍历列表得到key for key in key_list
从字典的get()方法,通过key得到value value=字典名.get(key)
print("%s:%s" % (key,value))
-------------------------------------------------------------------------------------------------------
方式2 先得到所有的键值对对应的列表 kv_list=dict.item()
遍历键值对的列表 for key_value in kv_list:
从键值对中得到key和value
key= key_value[0]
value = key_value[1]
print('%s: %s" % (key,value))
-------------------------------------------------------------------------------------------------------
遍历列表中的字典,实质上遍历出来的是这个字典对应的地址,在修改改完字典的内容后其地址没有改变,所以不需要重新
再把字典追加到列表中
-------------------------------------------------------------------------------------------------------
set 集合
-------------------------------------------------------------------------------------------------------
set集合(使用{}装的内容不能重复,且单个出内容,的列表)
与列表类似,但是set集合中的元素是唯一的不能重复
定义格式
set集合名 = {元素1,元素2,.....}
空set集合的定义格式
set集合名 = set()
set集合添加元素
set集合名.add()
set集合更新元素
set集合名.updata((新的set集合))
set集合修改元素
先删除要修改的,然后再添加要添加的元素
set集合删除元素
set集合名.remove(要删除的元素)
set集合名.pop()删除随意一个元素
set集合名.clear()清理空set集合
set集合查找元素
for e in set集合名:
print(e)
set,tuple,list之间可以相互转换
set= set([list])
-------------------------------------------------------------------------------------------------------
函数 ---->具有一个独立功能的代码块
可以让代码变得更加简洁
尽量避免代码重复
提高函数体代码的使用率
-------------------------------------------------------------------------------------------------------
定义函数的格式
def 函数名():
函数体 (就是一个语句体)
调用函数的格式
函数名()
-------------------------------------------------------------------------------------------------------
如果只定义了函数而没有调用,函数里的代码是不执行的
-------------------------------------------------------------------------------------------------------
将鼠标放在函数名上按 CTRL+Q 键查看函数文档注释
-------------------------------------------------------------------------------------------------------
带参数的函数及其调用格式
def 函数名(形参1,形参2, ....)
函数体
函数名(实参1, 实参2, ....)
-------------------------------------------------------------------------------------------------------
函数返回值
如果调用完一个函数之后,函数交给了调用者一个结果数据
这个数据就是返回值
调用者想在后续的代码中使用这个数据
需要在函数的最后使用return语句返回一个数据
-------------------------------------------------------------------------------------------------------
定义带有返回值的函数语法格式
def 函数名(形参1,形参2, ...):
函数体
return 数据
函数名(实参1, 实参2, ...)<---return就是吧数据返回到这里
这样的函数调用后return会吧得到的数据交给调用者
-------------------------------------------------------------------------------------------------------
函数的六个细节
1.保存函数的返回值--> 其实就是把这个返回值赋值给一个变量
2.直接打印函数的返回值 --> 直接使用print()函数打印
3.函数可以没有返回值--> 没有返回值就是None,表示什么都没返回
4.函数中连续写了多个return语句--> 只会执行第一个return语句,执行完return语句就表示函数调用结束了
5.return语句后不跟返回的数据--> 表示没有返回值
6.同一个程序文件中函数不能重名--> 会使用后定义的函数覆盖之前定义的函数
-------------------------------------------------------------------------------------------------------
函数的嵌套的格式
def function1 ():
...
def function2():
...
function1()
-------------------------------------------------------------------------------------------------------
局部变量
在函数里面定义的变量(作用域,有效范围-->只能在函数里面使用)
形参是在函数内部,所以也是局部变量
全局变量
在函数外面定义的变量(作用域,有效范围-->整个程序文件,必须先定义后使用)
使用global声明全局变量
在函数内部对全局变量赋值,实质上并不是在修改全局变量的值,而是在函数内定义了一个重名的局部变量
-------------------------------------------------------------------------------------------------------
要想在函数内部修改全局变量的值,必须使用global声明全局变量
格式: global 全局变量名
-------------------------------------------------------------------------------------------------------
函数里面尽量不要定义与全局变量重名的变量
-------------------------------------------------------------------------------------------------------
要想在多个函数中使用同一个数据需要用一个全局变量来存储这数据
-------------------------------------------------------------------------------------------------------
return 返回多个数据
把多个数据都写在return后面,使用逗号隔开
return 数据1, 数据2,数据3, .....(python解释器会把这些数据组包到一个元组中并返回,所以返回的值得类型是元组)
-------------------------------------------------------------------------------------------------------
参数的分类
默认参数(缺省参数)
默认参数必须在形参列表的最后
默认参数-->在定义函数时,给形参指定了默认的值,这个形参就叫做默认参数,也叫做缺省参数
调用函数的时候传值了就使用传的值,若没有传值,就使用默认值
关键字参数
关键字参数必须在实参列表的最后
再调用函数的时候按照形参的名字给形参传
在调用函数是,不需要按照形参的顺序传值
可变参数(不定长参数)
可变参数(不定长参数)只能位于形参列表的最后
在形参前面加上一个"*"号(表示任意多个参数)
def sum (* args)
sum()
调用传值时候把 多个实参放进一个元组,把这个元组传递给*args
函数变得更加灵活,提高了函数的扩展性
-------------------------------------------------------------------------------------------------------
在形参前面加两个**这样的可变参数只能接收一个字典类型的值
def sun (** kwargs)
print(kwargs)
sun(m=10,n=20,h=30)
调用传值时候把 关键字实参放进一个字典,把这个字典传递给可变参数**kwargs
-------------------------------------------------------------------------------------------------------
混合参数使用的规范
没有固定顺序,按照报错进行修改
-------------------------------------------------------------------------------------------------------
传参的时候在实参前加*可以将元组实参拆开
传参的时候在实参前加**可以将字典实参拆开
-------------------------------------------------------------------------------------------------------
组包和解包
组包-->把多个数据组装到一个容器中
如:a=10,20那么print(a)为(10,20)的tuple类型的元组
解包-->把容器中的元素拆解出来
如;i, j=(10,20)那么print(i)为int类型的10,print(j)为int类型的20
-------------------------------------------------------------------------------------------------------
a=10
b=20
自动解包交换a,b的值
a,b = b,a
-------------------------------------------------------------------------------------------------------
内功修炼大法
引用-->数据在内存中对应的地址
修改变量的值实质上就是在修改变量的引用
小数字:-5--256的数字
短字符串:长度小于20的字符串
这俩个也叫缓存池
可变类型与不可变类型
改变数据就改变地址的变量是不可变类型(如int,tuple,bool,str,float)
改变数据但是不改变地址的变量就是可改变类型(如 list,dict,set)
引用作为参数传递
不可变类型引用传递
不可变类型的数据是无法更改的 比如a=10,就是10,没法改变
参数传递都是引用传递,传参的时候传的是地址(id),并不是数值
可变类型引用传递
可变类型的数据是可以更改的 比如list1[]加数据减数据它还是list1[]
-------------------------------------------------------------------------------------------------------
可变类型的影响
定义函数的时候创建一次,以后调用就不再重新创建
+= 和 =+的区别
如果定义的变量 是不可变类型+=和=+是一样的
如果定义的变量是列表
+=是追加,=+是通过创建第三个列表来存储新的列表
-------------------------------------------------------------------------------------------------------
匿名函数
定义的函数没有函数名
lambda 形参1,形参2,...:单行的表达式 或者 调用其它函数的语句
如; lambda a, b:a + b --> a,b是形参,a+b是返回值
如果调用的其它函数没有返回值,那么匿名函数就没有返回值
调用匿名函数的格式
先把匿名函数赋值给一个变量-->变量名=lambda a,b;a+b
然后使用变量名进行调用-->变量名(实参1,实参2,...)-->sum(10,20)
匿名函数与普通函数的区别
匿名函数后只能写一行条件表达语句不能使用if,for,while,返回值是不需要使用return,条件判断语句的结果就是返回结果
应用场景
简化简单的普通函数
如果一个函数的功能只使用一次就可以使用匿名单数进行定义
作为函数的参数传递
-------------------------------------------------------------------------------------------------------
递归函数(在定义函数时,在函数里面自己调用自己)
递归 :一步一步的推导,一步一步的回归
在函数中自己调用自己,并且需要设置终止递归的条件
python中递归的层次(深度)不能超过1000次
应用场景
总功能分解出来的小功能的计算逻辑与总功能的计算逻辑相似
-------------------------------------------------------------------------------------------------------
-------------------------------------------------------------------------------------------------------
模块
一个.py文件就是一个模块
导入模块步骤
import 模块名(.py文件名)
通过模块名调用变量,函数或者类
模块名.(变量` 函数` 类)
-------------------------------------------------------------------------------------------------------
文件
把一些数据存储起来,永久保存
操作文件的步骤
打开问文件-->写数据-->关闭文件(释放文件所占用的内存资源)
f = open("文件的路径","操作模式")-->f.write("内容")-->f.close()
打开问文件-->写数据-->关闭文件
操作模式: write()存在的话就覆盖写入, 不存在就创建
读取文件的四种方式
一次读取几个字符
f.read(n) (返回一个字符串)
一次读取一行
f.readline() (返回一个字符串)
一次读取所有字符
f.read() (没有传递参数,默认读取所有字符,返回的是一个字符串)
一次读取所有行
f.readlines() (把所有内容打在一行,返回一个列表,列表里的每个元素是一个字符串)
-------------------------------------------------------------------------------------------------------
制作文件副本
打开源文件->截取源文件中文件的路径及其扩展名与 -副本 组成副本文件的名字->以只写的方式打开副本文件->从原文件中读取数据->把读到的数据写道副本中->关闭两个文件
得到最后一个.对应的索引,切片
index = 文件名.name.rfind(".")
-------------------------------------------------------------------------------------------------------
文件和文件夹的操作
import os
os.rename("旧路径+旧名字","新路径+新名字")重命名文件
os.remove("路径+文件名")删除文件
os.mkdir("文件夹名")--默认当前的工作目录
os.getcwd()-->get current work dirctiry
os.chdir("新的工作目录")
os.listdir("目标的目录路径")默认当前工作目录的文件和文件夹列表
os.rmdir("目标文件夹的路径")-->只能删除空的文件夹
-------------------------------------------------------------------------------------------------------
批量修改文件名
得到指定目录下的列表
遍历文件列表,每个元素都是文件的名字(字符串类型的)
文件名.replace()
-------------------------------------------------------------------------------------------------------
面向对象
面向--面对,看重
对象--通过类找到可以帮助你的对象
好处
开发效率高
可维护性强
可拓展行强
类与对象的关系
对象是通过类找到的
类: 描述现实世界中的某一类事物功能一样的事物,共同的信息,
把那一类事物的共同信息抽取出来,写到类中
属性:从静的一方面描述的信息. 如(颜色,年龄,体重)
行为:从动的一方面描述的信息,这一类事物能够做的事情.如(吃饭,睡觉,敲代码)
类 是从属性和行为两方面来描述 那一类事物的
在类中 属性:变量 行为:方法(函数)
对象
那一类事物中的任意一个个体
对象是通过类创建出开的,先有类,后有对象
面向对象必须按照步骤开发
定义类
创建对象
通过对象调用方法(调用方法时,不需要给self形参传值)
类的构成
类的名称:类名
类的属性:一组数据(变量)
类的方法:允许对类进行操作的方法(行为就是函数)
类的命名规则按照"大驼峰命名法"
当对象在调用这个方法 时会将对象的的引用(在内存中的地址)作为参数传递给self,通过self的值来确定是谁在调用这个方法
抽象---抽取相似的东西
-------------------------------------------------------------------------------------------------------
给对象添加属性
__init__(self)方法: 初始化对象,给对象添加属性-->通过self添加:
格式:self.属性名 = 属性值 如:self.name="张三
当对象创建时立即就添加了__init__()方法中的属性
通过对象访问属性
对象名.属性名
-------------------------------------------------------------------------------------------------------
通过对象名添加
对象名.属性=值(非常不建议使用需要添加属性,才能调用)
二次给属性赋值就是在修改属性的值
在其它方法中添加
对象.属性=值(非常不建议使用需要先调用才能添加属性)
-------------------------------------------------------------------------------------------------------
__str__(self)方法: 查看对象中自定义 的数据(属性值),打印对象可查看对象的数据
打印对象打印出来的是对象调用的方法的返回值 必须有一个字符串类型的返回值
如果不是字符串类型的数据需要使用str(),把对象转成字符串是得到对象中的数据
查看对象的属性时不用给str设置形参,调用对象时会将对象的属性通过self作为形参传递过去
打印对象时杯python解释器自动调用
-------------------------------------------------------------------------------------------------------
__del__(self)方法: 做临终遗言的事情 如:验证对象是否杯销毁,对象已杯释放(删除)
对象不被销毁就不会调用这个方法
对象即将被销毁但还没有被销毁的时候被python解释器自动调用
对象在没有被引用时才能被销毁
-------------------------------------------------------------------------------------------------------
对象可以作为参数传递,减少调用时形参的数量
-------------------------------------------------------------------------------------------------------
私有属性
不能在类的外面直接访问,只能在类的里面访问,通过self访问(在类的里面访问和访问公共属性格式一样)
定义格式
在属性名的前面加两个下划线
如 self.__属性名=属性值
在类外面访问属性,需要在类的里面使用set方法给私有属性赋值
在类的外面使用后get方法得到私有属性的值
可以在类里面设置过滤条件来保护私有属性
私有方法
只能在类的里面访问
定义格式
def __方法名(self,形参..):
方法体
-------------------------------------------------------------------------------------------------------
封装: 把不需要 对外暴露的代码隐藏起来就是封装
定义一个类,把属性和方法封装到一个类中(创建出来的对象就有这些属性和方法)
方法(函数)本身就是封装(把代码块写道一个函数或者是方法中)(直接使用函数或者方法)
把属性或者方法定义成私有的也是 封装(保护私有属性和私有方法)
对外只暴露功能,隐藏实现细节
-------------------------------------------------------------------------------------------------------
描述的是什么就定义他的类,长得什么样就定义什么属性 有哪些行为就定义哪些方法
-------------------------------------------------------------------------------------------------------
继承 (不存在爷爷类,都是叫父类,基类)
继承是描述多个类之间的所属关系
子类一旦继承了父类,子类中就拥有了父类中所有的非私有方法
定义格式
class 子类名(父类名)
子类中定义的方法列表
-------------------------------------------------------------------------------------------------------
object类 -->是所有类的父类(基类)
定义类时如果没有直接继承其他父类,默认就是继承了object类
-------------------------------------------------------------------------------------------------------
子类不能继承父类的私有属性和方法
__属性名= 属性值(私有属性)
def __方法名(self):
方法体
-------------------------------------------------------------------------------------------------------
子类重写父类中的方法
在子类中定义一个和父类名字一样的方法,以此来满足子类的需要
使用对象调用这个方法时就会调用子类中的修改过的方法
-------------------------------------------------------------------------------------------------------
在在类中调用父类被重写的方法
先重写父类中的方法
在重写的方法中使用 super().方法名(实参1, 实参2..)
父类名.方法名(self,实参1, 实参2...)
super(子类名,self).方法名(实参1, 实参2..)
-------------------------------------------------------------------------------------------------------
子类如何调用父类中的私有属性和方法
可以在父类中定义一个公共方法来访问私有属性私有方法
然后再子类中调用这个公共方法
如果父类和子类中都使用init方法添加了属性(相当于是重写了父类中的init方法),子类如何继承父类中的属性
需要使用super().方法名(实参1,实参2)来使用父类中的属性
-------------------------------------------------------------------------------------------------------
多层继承
A-->B-->C 使用super往基类继承
-------------------------------------------------------------------------------------------------------
多继承
子类同时继承了多个父类
定义格式:
class (父类1,父类2,...)
子类中的代码
子类的亲父类是离他最近的那个,就是括号里最左的,父类1
父类都有的方法及属性只会继承父类1的
想要调用其他父类中的方法可以通过父类名来调用父类名.方法名(self,实参1, 实参2...)
-------------------------------------------------------------------------------------------------------
实例就是对象 实例化就是创建对象
通过类名创建的对象都是实例对象
给实例对象添加的属性就是实例属性
实例属性是存储在实例对象里面的属于实例对象的属性
实例方法 第一个形参是self的方法就是实例方法
实例方法是属于实例对象
-------------------------------------------------------------------------------------------------------
类对象
定义的任何一个类都是一个类对象(类就是类对象)
对象的名字就是类名
元类:type类是用来描述所有的类的类对象的类型是type类型
类属性
类对象名.类属性 = 类属性值
定义在类的里面方法的外面
类属性是属于类对象的
类属性是所有实例对象共享公用的数据,每一个实例对象都可以使用这个类属性,不专属与某一个实例对象的
类属性的访问方式
实例对象名.类属性名
类对象名.类属性名(推荐! 可以节省实例对象占用的内存空间)
类属性可以定义成私有的,类属性名前面加__
类属性只能通过类对象修改,实例对象无法修改
类对象名.类属性 = 新的类属性值
-------------------------------------------------------------------------------------------------------
类方法
定义格式
在方法定义的上面使用装饰器 @classmethod 把下面的方法定义为类方法
如
@classmethod
def 方法名.(cls, 形参,形参):
方法体
第一形参必须是 cls(类对象)
访问方式
实例对象名.类方法名()
类对象名.类方法名()
-------------------------------------------------------------------------------------------------------
静态方法
特点
定义的时候需要用到装饰器:@staticmethod这个装饰器用来表示下边的方法是静态方法
静态方法中无法访问实例属性实例方法(得不到self)
可以访问类属性.类方法
定义格式
在定义方法的上面一行使用装饰器@staticmethod
第一个形参是普通参数,不能是self 或cls
调用方式
实例对象.静态方法名(实参1,实参2..)
类对象.静态方法名(实参1,实参2..)(推荐!!)
由来
工具类里面定义的方法一般都是静态方法
-------------------------------------------------------------------------------------------------------
多态
多态只是一种写法
在调用父类方法的地方也可以调用子类的方法的情况就叫多态
使用多态的步骤
子类继承父类
子类重写父类的方法
通过子类对象调用这个重写过的方法
提高函数/方法的拓展性,可维护性
-------------------------------------------------------------------------------------------------------
异常
程序中报出来的错误信息
异常类
用来描述某一类异常,python解释器自带了很多个异常类
异常如果不处理python解释器会在控制台打印错误信息,并终止程序运行!
处理异常的目的
保证后续的代码能够正常运行
python解释器处理异常的原理
python解释器在出错的那一行代码的地方根据错误原因选择异常类创建对象然后向外抛出,抛给她的调用者
调用者无法处理然后一层一层继续向外抛出
最后抛向python解释器
python 解释器最后在控制台打印错误信息,并且终止程序运行!
-------------------------------------------------------------------------------------------------------
处理异常的基本格式
try:
可能出现异常的代码块
except:
处理异常的代码块
except后面跟上你觉得会出现的异常的类型(如果不确定异常类型就是用Exception),然后as给一个变量,可以打印变量得到异常的类型
先执行try里面的代码,看是否出现异常
如果出错就会执行except里面的代码,如果没有出现异常就不会执行except里面的代码
-------------------------------------------------------------------------------------------------------
怀疑哪些代码会出现异常,就用try...except..将它们包起来
-------------------------------------------------------------------------------------------------------
处理异常的三种方式
一次性全部捕获,一次性全部处理(不智能,需要人为再取分析,except后面跟上你觉得会出现的异常的类型,然后as给一个变量,可以打印变量得到异常的类型)
分别捕获,分别处理(每一行都使用try...except..进行捕获,也可以打印错误类型,不建议使用)
一次捕获,分别处理()
try
可能出现异常的代码块
except 异常类型名 as 异常变量名:
打印异常变量名
except 异常类型名 as 异常变量名:
打印异常变量名
except 异常 类型名 as 异常变量名:
打印异常变量名
....
-------------------------------------------------------------------------------------------------------
处理异常的格式
基本格式:
try:
可能出现异常的代码块
except:
处理异常的代码块
else格式
try:
可能出现异常的代码块
except:
处理异常的代码块
else:
没有出现异常时一定会执行的代码(用来验证怀疑的代码是否有异常)
如果出现异常就会执行except里面的代码,不会执行else里面的代码
如果没有出现异常,就会执行else里面的代码,不会执行except里面的代码
finally格式
try:
可能出现异常的代码块
except:
处理异常的代码块
finally:
不管有没有出现异常,也不管异常有没有被捕获住一,定会执行的代码
(通常用来做释放资源的事情,比如关闭文件,关闭数据库连接)
-------------------------------------------------------------------------------------------------------
异常的跨函数传递
python解释器在出错的那一行代码的地方根据错误原因选择异常类创建对象然后向外抛出,抛给她的调用者
调用者无法处理然后一层一层继续向外抛出
最后抛向python解释器
python 解释器最后在控制台打印错误信息,并且终止程序运行!
异常被捕获主之后,后续的try就无法捕获住这个异常了
-------------------------------------------------------------------------------------------------------
自定义异常类
当python解释器提供的异常类不能满足足自己的需求时
自定义异常类步骤:
自己定义一个类,继承任意一个异常类
在自定义类中添加一个初始化方法
class AgeError(Exception):
def __init__(delf,msg):
self.msg = msg
抛出异常对象
先创建一个异常对象,然后使用raise关键字向外抛出
raise AgeError("msg的内容如提示信息等")
-------------------------------------------------------------------------------------------------------
模块
一个.py文件就是一个模块
可以在模块中定义全局变量,函数.类
使用import导入
使用模块名.全局变量名
模块名.函数名
模块名.类名
调用
好处就是可以一一对应进行调用
其它导入方式
import 模块名 as 别名
可以将模块名进行缩短,使用别名调用,写少些字
from...import....
from 模块名import 全局变量名, 函数名, 类名 -->也可以使用as取别名
需要使用 啥就导入啥
from 模块名 import *
使用时需要在模块文件中使用__all__变量定义希望以这种方式导入的东西 格式为__all__ = ["全局变量名","函数名","类名等"]
-------------------------------------------------------------------------------------------------------
__name__变量
如果文件时主动执行文件,__name__变量的 值就是main
如果文件时被动执行文件,__name__变量的 值就是文件名(模块名)
在模块文件中使用,不希望测试代码在调用时被执行显示
if __name__ == "__main__":
测试代码块
-------------------------------------------------------------------------------------------------------
包
工程目录下面的一个文件夹
创建包就是创建文件夹
用来分类管理工程文件,
经常按照功能来管理功能模块
包的命名规则与变量的命名类似
多层包命名格式
com.项目名.包名
项目名按照大驼峰命名规则
英文单词的缩写,取首字母大写
导包是为了导入模块文件
访问包里面的模块文件时需要把包名的路径写全
导包的方法
import 包名
在init文件名中使用 from.import文件名 确定需要导入的文件
在调用的时候配合 import包名 使用
import 包名.模块名
import 包名.模块名 as 别名
from 包名.模块名import ...
from 父包名.子包名.模块名 import ...
from 包名 import *
在__init__文件中必须使用__all__指定需要导入的模块名
格式: __all__ = ["模块名1". "模块名2", ....]
-------------------------------------------------------------------------------------------------------
enumerate()
enumerate()函数用于将一个可遍历的数据对象(如列表、元组或字符串)组合为一个索引序列,同时列出数据和数据下标,一般用在 for 循环当中。
vim -ON 文件1 文件2 文件3 ---> vim同时打开多个文件
GIL 全局解释器锁
保证了同一时刻只有一个线程可以使用cpu 一个进程只有一个GIL锁
线程抢到GIL锁就可以使用cpu 并发交替执行任务
也有可能各抢到一半,时间片极短,资源监控无法监控到这么短的时间 其实在这个时间段此线程是100%占用cpu
GIL 对进程不会造成影响
GIL锁会释放的情况
1 线程超时
2 线程遇到阻塞
3 线程执行完成
sudo apt-get install lrzsz -y 安装Xshell上传下载文件
rz 上传 sz下载
sudo apt-get install rar
安装rar
cpu检测工具 ps aux静态显示 top动态查看cpu后台使用情况 htop更加清晰地查看cpu后台使用情况
python 解释器默认是cpython 解释器 天生存在GIL锁-->全局解释器锁
多线程爬取网络比单线程性能高 因为遇到IO阻塞 会自动释放GIL锁
IO 密集型 使用cpu过程中cpu有空闲 网络地收发 文件地读写
解决GIL的三种方式
1 换成非Cpython解释器
2 使用多进程
2 使用其它语言
用C语言实现
将c代码编译成动态库
gcc xxx.c -shared -o libxxx.so
在python文件中导入并调用c的动态库
多线程任务使用c的函数 用以解决GIL锁的问题
深拷贝 浅拷贝
浅拷贝
copy 模块的copy函数 copy.copy()
变量之间的赋值 本质上就是 引用的传递
优点 1节省有限的空间 2 节省时间 节省创建的时间
缺点 无法保证数据的独立性 解决方式 使用深拷贝
a = [元素1的地址,元素2的地址]-->列表a的地址
|^等于^| |^等于^| |不等|
b = [元素1的地址,元素2的地址]-->列表b的地址
浅拷贝copy.copy()对于可变数据类型对象拷贝时,仅仅是拷贝顶层对象(子元素指向引用),不考虑元素的类型
浅拷贝copy.copy()对于不可变数据类型对象拷贝时,引用指向 不考虑子元素数据类型
深拷贝
copy模块的deepcopy()函数 copy.deepcopy()
深拷贝copy.deepcopy()对于可变数据类型,要做顶层拷贝,子元素是否拷贝要看数据类型(不可变数据类型引用指向,可变数据类型拷贝)
深拷贝copy.deepcopy()对于不可变数据类型对象拷贝时,子元素都是不可变数据类型,不拷贝引用指向,
深拷贝copy.deepcopy()对于不可变数据类型对象拷贝时,如果子元素存在可变数据类型,要拷贝顶层对象,并且拷贝元素
import 模块 和 from 模块 import * 的区别
sys模块 中的变量path
sys.path 表示 解释器寻找模块要扫描的路径
path 的返回值是一个列表
[
第一行''表示当前路径
]
可以将要添加的模块文件路径添加到sys.path中
sys.append("要/添加/的模块/的路径) 然后再使用import 导入模块文件名
临时性添加,环境关闭后就消失了
sys.path.insert(位置索引,"要/添加/的模块/的路径") 然后再使用import 导入模块文件名
临时性添加,环境关闭后就消失了
+----------------------------------------------------------------------------+
| 将模块文件的路径添加到 系统环境变量的配置文件(.bashrc)中 在文件末尾添加 |
| vim .bashrc 打开 |
+ export PYTHONPATH=$PYTHONPATH:要/添加/的模块/的路径 +
| 保存退出 |
| 刷新文件 source.bashrc |
| 永久添加模块文件的路径 (可以用来添加第三方模块) |
+----------------------------------------------------------------------------+
修改模块文件内容后需要重新加载模块文件
import 导入模块只有第一次导入生效,以防止重复导入
如需要修改模块文件内容,需要重新加载模块
from imp import reload
reload(模块文件名)
前单置下划线的变量在使用 "from 模块名 import *" 时 禁止导入, 在使用import * 时可以导入
如_name = "XX"
python源.py文件命名并没有特殊限制,但是要将源.py文件作为模块文件名的话就必须遵循变量名命名规范(数字,字母,下划线组成,且不能以数字开头),也不能与系统模块名同名 如(socket,re,os,random...等)
多模块开发的注意点
import 模块名 调用模块中的函数,变量 -->模块名.函数名()/变量名
from 模块名 import * 调用模块中的函数,变量 -->直接调用 函数名()/变量名
from 模块名 import * 导入的数据时导入所有-->把变量的值也导入 如变量值是不可变类型,那修改变量的值就失败 调用的时变量的值依然是原值
封装继承多态进阶
封装
将代码放进类里面便于代码的维护升级
继承
减少代码的重用 直接继承父类的方法
多态
继承父类
重写父类的方法 添加自己的需求
将子类的实例对象作为的参数传到平台中
再调用父类的方法
实例对象 不能直接访问私有属性
但是可以通过 "实例对象._类名__私有属性" 名字重整将私有属性封装起来 间接进行访问 但是最好不用要自觉
正则表达式
从杂乱无序的数据中按照某种规则查找,匹配或者替换为需求的数据.
导入 re 模块 re(正则表达式模块)
match() 匹配
变量 = re.match(正则表达式,要匹配的字符串) -->match 只顾头不顾尾
匹配失败返回None
通过group()方法获取匹配成功的数据
元字符 : 具有匹配单个字符的特殊符号
. 匹配任意一个字符(除了\n)
[] 匹配[]中列举的字符 [123]就是1 2 3 三个字符 [1-8]就是1到8
\d 匹配数字0-9
\D 匹配非数字
\s 匹配空格. tab键-->(\t)
\S 匹配非空格
\w 匹配非特殊字符,字母数字下划线汉字
\W 匹配非字母数字下划线汉字,特殊字符
* *前面的的一个字符出现任意多次
+ +前面的一个字符至少出现一次
? ?前面的一个字符出现1次或者0次
{m}前面的一个字符出现m次 m可以是个区间{2,5}-->2,3,4,5次都可以 {m,}m次到无限多次
^ 匹配以什么开头 ^[xy]-->表示以什么或什么开头 [^xy]-->表示不以什什么都可以
$ 匹配以什么结尾 从后往前找和开始将字符夹在在中间$
匹配分组
| 匹配左右任意一个表达式 --- 把多个字符放到分组中-->(a|b|c|d)括起来!
分组默认是从1开始的
(ab) 将括号里的字符作为一个分组
\num 引用分组num的数据 \1就是分组1
(?P<别名>正则表达式)
re模块的高级用法
import re
search() 查找 返回一个对象
默认只查找一次,不是从头开始查找
findall() 返回一个匹配成功的列表
sub("正则表达式","替换后的数据","要替换的数据,count=替换的次数,默认为零全部替换") 替换
返回一个字符串--
split("正则表达式","要切割的的数据",maxsplit=最大切割次数) 切割
贪婪 和 非贪婪
贪婪 在满足正则表达式的条件的情况下,取得越多越好
python 正则表达式默认是贪婪的
非贪婪 ?
?前面的正则表达式不能匹配?后面的数据
正则表达式前面加r就不用使用\进行转义
1个进程最多打开1024个文件
多继承 钻石继承--菱形继承
多继承单独调用父类的方法
class Parent()
class Son1(Parent)
父类名.方法名
class Son2(Parent)
父类名.方法名(self,参数)
class Grandson(Son1.Son2)
父类名.方法名
父类名.方法名
GrandSon类的实例对象
导致顶层父类被调用两次
解决方法 使用super()调用父类方法 -- MRO顺序
定义方法(self,参数,不定长参数组包接受多余参数)
super().方法名(参数,不定长参数解包)-->参数不需要self
查看MRO顺序表(当前类名.__mro__)
调用顺序由MRO顺序表决定
当前类去MRO顺序表中查找当前的类,如果相等,就调用当前类在MRO顺序表中的的下一个类的重写的方法
super() 可以指定要调用的父类
super(指定父类名,self).方法名(参数,不定长参数解包)
再去MRO顺序表中找指定的父类名,调用指定的父类的下一个类的重写的方法
MRO顺序表是由python解释器中的C3算法产生的
不定长参数拆包
*args 在定义函数时作为参数的功能是组包
**kwargs 在定义函数时作为参数的功能是组包
*args 在调用时作为函数参数 的功能是拆包
**kwargs 在调用时作为函数参数 的功能是拆包
property 属性
在定义时像函数一样 在使用时像属性一样 的特殊属性
把方法封装成属性,简化调用流程
创建的两种方式
1 装饰器
@property 创建属性--------->使用实例对象调用
@方法名.setter设置属性值 -->使用实例对象赋值调用
@方法名.deleter删除属性值-->使用del 调用
2 类属性
创建类:
def __init__(self): 初始化
def get(self): 获取值
def set(self,参数): 设置值
def del(self): 删除值
类属性 = property(get,set,del,"description...")-->四个参数
创建实例对象
实例对象.类属性 获取实例对象值
实例对象.类属性=值 设置实例对象值
del 实例对象.类属性 删除实例对象值
type 创建 -->类对象创建 -->实例对象
type类是所有类的祖宗类 type类由type类自己本身创建type类是造物主 object类也是由type类创建的
魔法属性/魔法方法
__doc__
类的描述信息,就是类的注释
__module__():
当前操作对象在哪个模块
__class__():
当前操作对象的类是什么
__new__():---+
开辟内存 |
__init__():--+
初始化方法,创建类时自动触发执行
__del__():
对象在内存中即将被释放时自动触发执行 释放实例对象占用的内存
__call__():
实例对象后面加括号自动触发执行
__str__():
打印对象的属性信息时返回该对象的信息
__dict__
类和对象里的所有属性
__getitem__():
__setitem__():
__delitem__():
把实例对象当作字典使用
实例对象可以访问实例方法,类方法,静态方法
类对象可以访问类方法,静态方法,不可以访问实例方法,实例方法属于实例对象
hasattr(对象,"要查看的属性")
查看对象有没有这个属性 有True 无 False
getattr(对象,"要获取值的属性")
获取对象指定的属性的属性值
setattr(对象,"属性","值")
设置对象的属性值
with 与 上下文管理器
with open("文件的路径","方式") as f:
f.write("数据")
上下文管理器
本质上就是能够支持with操作
任何实现了__enter__()和__exit__()方法的对象都可以称之为上下文管理器,上下文管理器对象可以使用with方法
定义一个类:
初始化
文件名
操作方式
__enter__()方法返回资源对象,就是你将要打开的那个文件对象-->上文 完成一些相关的操作
self.f = open (self.文件名 ,self.模式)
return self.f
__exit__()方法处理一些资源清楚工作------------------------>下文 释放资源的操作
self.f.close()
使用上下文管理器
with 类名 ("文件路径", "模式") as f:
f.write("数据")
open()方法里面已经实现了上下文管理器,所以打开操作文件时可以直接使用 with open()...
使用contextmanager 实现上下文管理器
from contextlib import contextmanager
@contextmanager
def 函数(参数,参数):
上文
文件对象 = 打开文件
yield 文件对象
下文
关闭文件
使用上下文管理器
with 函数名 ("文件路径", "模式") as f:
f.write("数据")
函数名就是一个变量 指向引用的函数体的空间
函数名之间的赋值本质就是引用的传递
函数名可以作为函数参数进行传递
类对象就是类模板
闭包
就是一种节省内存资源的特殊语法 相比于面向对象占用更少的资源空间-->轻量级的面向对象
缺点:不能开发大程序,只能实现小的功能
闭包的三要素
1函数的嵌套定义
2内层函数使用了外层函数的变量或参数
3外层函数要返回内层函数的引用
定义闭包
def 外层函数(参数):
def 内层函数(参数):
内层函数的处理过程
return 内层函数的引用
实现 y = k*x + b
def func(k,b):
def create_y(x):
print(k*x + b)
return create_y
创建闭包
f1 = func(1,2)
f1(0)
f1(1)
f1(2)
修改闭包中的变量或者参数
定义闭包
创建闭包
闭包变量名() 调用的是内层函数
在内层函数中使用外层函数的变量 需要使用 nonlocal 变量名 进行声明
斜率? 拮据? 方程? 是什么?
匿名函数->a = lambda x ,y:x + y 完成最简单的功能 作为函数参数传递时完成的是 功能
函数----->完成较为复杂的功能 作为函数参数传递时完成的是 功能
闭包----->可以完成比函数更为复杂的功能 作为函数参数传递时完成的是 功能+数据(外层函数给的)
实例对象->可以完成最为复杂的功能 作为函数参数传递时完成的是 很多的功能+很多的数据
装饰器
作用 :在不修改函数的源代码的情况下对函数的功能实现拓展 要么在函数调用之前要么在函数调用之后添加
装饰器作用的对象就是: 函数或者方法
装饰器基于 闭包 经常用到的功能基础功能
装饰器的实现
定义 一个闭包
定义外层函数
定义内层函数
实现功能使用外层函数的变量或者参数
返回内层函数的引用
@外层函数名
定义一个函~数
函数体
函~数()-->调用内层函数
@外层函数名(装饰器的灵魂代码) 相当于 函~数 = 外层函数(函~数) 下面紧接着的是函数才进行装饰 否则不装饰
装饰器在函数调用之前就开始装饰了
装饰的顺序最靠近函数的先装饰
函数调用的顺序是从上往下
使用类作为装饰器
先定义一个类(继承自object):
初始化(形参)
self.形参 = xx
定义__call__方法():
return self.func()
@类名
定义一个函数:
函数体
return "----"
函数名()
使用同一个装饰器对不同的函数进行装饰时完成不同的装饰功能
真正实现
在装饰器@外层函数(参数)时传参
在定义闭包时添加一层外层函数
在内层函数中对参数进行判断
装饰器 遵循开放封闭原则--->不能对原来的函数进行修改,传参
miniweb 框架
框架的概念
静态资源 一般是不需要进行修改的资源 如图片(png,jpg,img)js资源,css资源,字体库等不需要经常修改的资源
动态资源 根据用户不同的需求返回不同的结果数据,一般就是从数据库中查询出来的数据
模板 具有一定格式的空网页
常见的web服务器
nginx apache lighttpd IIS
常见的web框架 flask django tornado web.py aiohttp sanic bottle vibora
web服务器 --WSGI协议-->web框架
sys模块的sys.argv 会获取命令行的参数以列表的方式保存
浏览器回车一次服务器端接受到多次请求 是因为 浏览器检查当前网页中还有新的连接请求会再次向服务器发送链接请求
format 格式化输出
---->>>{}<<<---.format(字符串)
服务端send数据发送不完整可以使用sendall()发送
html 可以作为静态资源文件也可以作为动态资源文件
作为静态资源文件时不需要修改html文件中的内容
作为动态资源时就是一个模板(具有一定格式的空网页),需要从数据库中查询出数据填充网页返回给浏览器
pycharm 遇到模块导入报红需要 刷新source 设置 -->项目-->选中当前文件夹
自己定义的包要想给别人使用需要在在包中创建__init__.py
WSFI协议框架 规定了服务器如何调用web框架,web框架如何将数据返回给web服务器 字典存储数据
打开模板文件 读取
with open("模板文件路径","r") as f
file_content= f.read()
模拟从数据库中查询数据
data_from_mydql = "have func"
将数据库中查到的数据替换模板中的{{content}}
html_content= file_content.replace("{{content}}",data_from_mysql)
返回替换后的数据
return ytml_content
路由
Django定义路由的方式 定一个路由表
route_list = [("页面路径",对应函数名),("页面路径",对应的函数名),("页面路径",对应的函数名),...]
添加路由 浏览器请求的路径在路由列表中存在遍历列表就可以了,免去繁杂的判断语句
flask 使用的是带有参数的装饰器
定义一个路由列表 route_list = []
定义一个闭包函数
def route(path):
def func(func):
route_list.append((path,func))
def inner();
pass
return inner
return func
@route("页面路径.html")
def 处理页面数据对应的函数():
pass
...
使用上下文管理器的方式操作数据库
class MySql(object):
def __init__(self):
self.conn=connect(host="localhost",port=3306,user="",password="",database=""cahrset="utf8")
self.cur=self.conn.cursor()
def __enter__(self):
return self.cru
def __exit__(self):
self.cur.close()
self.conn.close()
获取游标对象的数据 cur.fetchall()
a = ((1,2,3,4,5),(6,7,8,9,0))
for value in a:
print("%s:%s:%s:%s:%s" % value)
每个小元组中的元素会在自动填充占位符%s-->元组的格式化拼接