基础原理
语言类型:
-
分类:编译型、解释型,强类型、弱类型
-
编译型:编译完在执行
- 代表语言:C,C++
- 优点:运行速度快
- 缺点:开发速度慢
-
解释型:逐行编译
-
优点:开发速度快
-
缺点:运行速度慢
-
代表语言:Python,JavaS,PHP
-
-
编码:
- 8bit = 1byte 1024B(byte) = 1KB 1024KB = 1M
- ASCII: 英文编码 英文一个字节
- GBK : 国标码 英文 一个字节,中文两个两个
- Unicode: 万国码 英文两个 个字节, 中文四个字节
- UTF-8 : 万国码升级 英文一个字节, 欧洲两个字节,中文三个字节
python2和python3区别:
-
代码: python2 代码混乱,重复 python 源码规范,清晰,简单优美
-
编码: python2 编码为ascii python3 内存编码为Unicode
-
print: python2 中print不需要添加括号 python3 中需要添加括号了
-
input: python2 中输入是raw-input python3 中是input
-
nonload: python2 中没有nonload python3 中新加入的
-
类: python2 经典类,深入优先 python3 不存在经典类,都是新式类,mro算法也叫c3
基础数据类型:
-
字符串:str
- upper,lower,startwith,endswith,replace,strip,split,join,count,isdigit,index/find(不报错)
-
列表:list
-
append,insert,extend,pop,remove,del,改:li[] = "海洋" 查:根据索引,切片查询
count,index,sort,reverse
-
-
列表的注意事项:
- 循环一个列表时,删除元素时,剩下的值会向前近一步 (索引也会更改),
- 不要改变列表的大小,这样会影响你最终结果
-
列表去重:
- 方法一:
-
创建新的列表,for循环列表中每个元素是否不在新列表中,不在则追加
-
方法二:
-
l1 = [33,22,33,44,44,22,55,11] l2 = list(set(l1)) #set去重转成列表 l2.sort(key = l1.index) #使用列表进行排序,保证原顺序 print(l2)
-
-
列表删除:
-
列表删除只可从后往前删除,
-
a = [1,2,3,4,5,6,7,8] for i in range(len(a)-1,-1,-1): if a[i] > 5: a.pop(i) else: pass print(a)
-
-
字典:dict
-
增加:dic['name'] = ['hai'] 有则改之,无则增加 ,dic.setdefault("name","hai") 有则不变,无则增加
-
删除:dic.pop('key',)
-
修改:dic['name'] = 'junli'
-
查看:print(dic['name'],dic.get('name') #get没有返回none,好用!!!
-
fromkeys:
- 创建空字典:dic = dict.fromkeys("可迭代对象")
-
enumerate:
- 枚举,for i in enumerate(字典): 每次循环索引位置和key
-
update:
- dic.update('name','18') 添加
- dic.update(name = '太白金星') 更改
- dic.update([(1, 'a'),(2, 'b')]) 列表中的元祖添加到字典
- dic1.update(dic2) 更新:字典融合,有则覆盖,无则增加
-
-
元祖:tuple
-
只读列表,不可修改
-
tu1= (1) 如果元祖中只有一个元素,那么他还是本身元素
-
count 统计元祖中字符出现的次数
-
index 通过元素查找索引
-
-
集合:set
- set集合里存放的是可迭代类型
- 列表去重
- 交集,并集,差集(两个数据进行的操作)
文件操作:
-
文件操作的格式:
-
with open('文件的读',encoding='utf-8') as f1:
- print(f1.read())
- with: 使用with打开文件,不用关闭文件句柄
-
open: 是内置内置函数,调用操作系统的接口
-
encoding:设置文件读写编码格式,默认是操作系统编码
-
-
mode操作方法:
-
读取:r(默认是r) 追加:a ,写入:w 非文本文件不能指定编码:rb
-
先读后写(可以追加):r+
-
追加读:a+
-
-
文件句柄操作方法:
- read readline() write() read(n)按光标读 readlines()将内容聚合列表
-
替换文件:
-
# 另一种打开文件的方式: 帮助自动关闭文件;可以同时开多个文件,用逗号隔开;也可以同时操作一个文件 with open("a", mode="r", encoding="utf-8") as f,\ open("b", mode="a", encoding="utf-8") as f1: import os print(os.getcwd()) # 查看当前工作路径 os.remove() # 删除文件 os.rename() # 更改文件名.(新名,旧名)
Python 中的空间和作用域:
-
三个空间:
-
内置名称空间:当你运行python程序,会开启一个内置名称空间,将内置函数print等等加载到空间中
-
全局名称空间:加载当前py文件中的变量,和函数外声明的变量,加载到全局空间中,变量与值对应关系
-
局部名称空间:函数执行时,会开辟出局部空间(也叫临时名称空间)
-
-
globals() 查看全局存储的全局变量
-
locals() 查看当前存储的变量
-
全局作用域---->内置名称空间和全局名称空间
-
局部作用域---->局部名称空间
-
作用:
-
作用域对与变量而言,声明变量在程序里可使用的范围
局部作用域可以引用全局作用域变量,局部作用域不能改变全局变量
-
- 加载顺序:
- 内置--->全局--->局部 (从外到内)
- 取值顺序:
- 就近原则LEGB
同一代码块:
- 优点:能够进行复用,提高一些字符串,这样在数字处理时间和空间上提升性能,节省内存
- 适用对象:
- 列表,字典,可变的数据类型不会复用的
- int:任何数字在同一代码块下都会复用
- str:几乎所有的字符串都会符合缓存机制
不同代码块:
- 小数据池规则:
- 小数据池,是不同代码块下的缓存机制,也叫缓存机制和驻留机制,在编程语言当中都有类似的东西
- 主要是用于提高效率数字类型在时间和空间上的性能,避免创建重复的数据,节省内存
- 缓存规则:
- int:-5-256整数进行缓存,当你将整数赋值给变量时,直接引用已经创建好的缓存对象
- str:
- 1.字符串在做乘法(乘法不为1)的时候长度不能超过20
- 2.自己定义的字符串长度不限制,字符串必须是字母,数字,下划线组成
- 3.特殊字符定义1个的时候,进行驻留
运算符:
- 算数运算符:
* /
加减乘除 %取余 2**4 幂 //整除返回的部分
- 比较运算符:
- == 等于 !+ 不等于 >= 大于等于 <= 小于等于
- 逻辑运算符:
- 顺序:not >>> and >>> or
- x and y x 为真返回y x为假返回x
- x or y x为真返回x x 为假返回y
- not x x为真返回假 x为false返回true
深浅copy:
-
浅copy:
- 拷贝的数据半共享,当你浅copy一个嵌套的列表,将拷贝第一层数据会指向同一个内存地址,如果你修改数据,指向会断开,第二层数据也就是嵌套的列表他没有拷贝,元素的内存地址是共用的一个。
-
深拷贝:
-
拷贝的数据不共享,深拷贝他会逐层判断,将不可变的数据类型指向同一个内存地址,可变的数据类型跟原列表不共用一个,元素指向的内存地址都是一样的。
-
函数原理:
函数闭包:
-
闭包存在函数嵌套中,内层函数对外层函数中非全局变量进行了引用或者修改,这个变量就是自由变量,他不会随着函数的运行结束而消失,保证了数据安全
- 当自由变量被调用时,闭包形成
- 判断函数是不是闭包,print(ret.
__code__.co_
freevars)
-
作用:
- 保证了数据安全性,自由变量不会在内存中消失,而且全局还引用不到
-
应用环境:
-
用在与装饰器
-
开放封闭原则:
- 开放原则:在源码不改变的情况下,增加一些额外的功能
- 封闭原则:不改变源码,对与更改是封闭的。
- 装饰器符合开放封闭原则
函数:
-
函数是以功能为导向,一个函数封装一个功能,你写完这个函数可以随掉随用,函数他减少了代码的重复性,增强了代码的可读性
-
高阶函数:
- 一个函数可以作为参数传递给另一个函数,或者一个函数的返回值为另一个函数,递归也是高阶函数
- map filter reduce 都是高阶函数
-
匿名函数 lambda:一句话函数,用于内置函数,匿名函数结合内置函数使用
- func = lambda x,y : x+y 名字func :前形参 :后返回值
- 示例1:
- func = lambda x : (x[0],x[2]) 返回多个元素加()
- 示例2:
- func = lambda x,y :x if x > y else y
- func = lambda *args : max(args) #返回最大的值,也可以添加三元运算>
- 示例3:
- [lambda :i for i in range(10)] 这样的都是十个为9的内存地址,遇()执行
-
内置函数:***加key的 dict,abs,sum,min,max,sorted,map,reduce,filter(68种)
-
float int list dict set tuple id len next type input print help
-
加key的格式:
- 将最小的值返回,dic[x] 返回值是什么,就按什么比大小***
- dic =
- print(dic[min(dic,key=lambda x:dic[x])]) key=lambda 函数名 :前形参 :后返回值
-
-
函数名应用:
- 函数名就是变量
- 函数名加()执行
- 函数名可以作为容器类型(list)的元素
- 函数名可以作为函数的参数传递
- 函数名可以作为函数的返回值
函数参数:
-
*的魔法作用:
-
*args 位置参数聚合成一个元
-
kwargs 关键位参数聚合成一个元
-
实参加* 代表打散,聚合给*arg
-
实参加** 代表打散,只能用于字典,聚合给**kwargs 打散的key不能是int类型
-
参数说明:
-
位置参数:从左至右,一一对应
-
默认参数:传值覆盖,不传则默认
-
仅限关键字参数:放在默认参数后面
-
-
形参顺序:
- 位置参数,*args,默认参数,仅限关键字参数,**kwargs
-
实参顺序:
- 位置参数,关键字参数,混合参数(位置参数,关键字参数)
-
注意事项:
- 默认参数的坑,当你的默认参数是可变类型,不会消失,使用的是同一个内存地址。
- 函数名指向的是函数的内存地址,加上()就可执行。
-
示例:
-
def func(a,*args,sex='男',c,**kwargs,): print(a) print(sex) print(args) print(c) print(kwargs) func(1,2,3,sex='女',name='海洋',age=18,c='666')
-
-
当函数的实参位置不传值的话,可变数据类型不会消失,会使用同一个内存地址
-
def f(x,l=[]): for i in range(x): l.append(i*i) print(l) f(2) f(3,[3,2,1]) f(3)
-
递归函数:
-
递归函数就是自己调用自己
函数或者其他代码都可以解决递归解决的问题,但是递归在某些时候能够出奇制胜
人理解函数,神理解递归
-
默认的递归次数:
- 1000(次数越多,速度越慢)
- 递归根本:逆推,要有终止条件return
-
递归示例1:
-
#打印列表中的每个值 l2 = [1, 3, 5, ['海洋','俊丽', 34, [33, 55, [11,33]]], [77, 88],66] def func(alist): for i in alist: if type(i) == list: func(i) # func(['海洋,'俊丽',34]) #当i为列表时一直调用本身,节省for循环 else: print(i) func(l2)
-
-
递归示例2:
-
#循环获取路径下的文件 import os li = [] def dir(path): path_file = os.listdir(path) #os.listdir 已列表的形式获取目录中文件夹和文件 for i in path_file: if os.path.isdir(os.path.join(path, i)): #判断是否为目录 dir(os.path.join(path, i)) #将使用jion拼接使用函数再次调用给函数本身 else: li.append(os.path.join(path, i)) #是文件就返回 return li print(dir(r'路径'))
-
-
递归示例3:
-
import os import re li = [] def dir(path): path_file = os.listdir(path) #os.listdir 已列表的形式获取目录中文件夹和文件 for i in path_file: if os.path.isdir(os.path.join(path, i)): #判断是否为目录 dir(os.path.join(path, i)) #将使用jion拼接使用函数再次调用给函数本身 else: li.append(os.path.join(path, i)) #是文件就返回 return li dir(r'E:\Pycharm-代码\作业\23期\day27-网络编程') for png in li: if re.findall("png",png) == ["png"]: #使用re模块findall判断文件是否已png结尾 jpg = str(png).replace(".png",".jpg") #将png路径替换成jpg os.rename(png,jpg) #文件重命名
-
列表推导式:
简单,快捷,装逼
- 循环模式:
- li = [i for i in range(2,101,2)] 构建1-100的偶数
- 筛选模式:
- [i for i in range(1,31) if i %3 ==0 ] if筛选能被3整除的
生成器表达式:
- (i for i in range(1,11)) 使用()扩起来就可以了, 就是生成器表达式
可迭代对象:
-
可以重复迭代取值的一个工具,内部含有
__iter__
方法的就是可迭代对象查看是否含有可迭代对象方法if
__iter__
in dir() -
优点:
- 可迭代对象是一个操作方法灵活,侧重于对少量数据灵活处理(并且内存足够)
-
缺点:
- 占用内存
- 不能迭代取值(索引,字典的key)
迭代器 ltertor:
-
可以重复迭代的工具,内部含有
__iter__
和__next__
方法就是迭代器,
iter方法是将可迭代对象转换成迭代器
next方法是迭代器进行取值(无法找到下一个结果时会出现StopIteration异常)
-
优点:迭代取值,节省内存(迭代之后元素消失),惰性机制不走回头路
-
缺点:操作方法少,不直观,查询速度较慢(时间换空间)
-
作用:
*为什么要使用迭代器,当你要获取文件内容时,传统方式是读取文件内容到内存空间中,在使用
for循环遍历,如你文件较大,这样会占用极大的内存空间,而使用迭代器是可以一个迭代读取一
段内容,节省内存空间,这也是迭代器存在的作用
- 使用环境:
- 逐行遍历文件内容,构建和扩展集合类型,元祖拆包
生成器:
-
生成器的本质就是迭代器,函数中包含yield方法,是生成器函数。
-
生成器产生方式: 生成器函数(yield和yield from) 生成器表达式() python内置函数 lamdba
-
取值方式:next() for循环 list列表
-
yield:
- 函数中包含yield方法,是生成器函数,当你去调用函数的时候,返回值是一个生成器地址,当你想执行内容需要调用next()方法
-
yield from:
-
代替了生成器函数里的内层循环,在函数中如果yield from list 会将list可迭代对象变成迭代器返回
-
-
迭代器和生成器区别:
-
可迭代对象和迭代器的区别:
-
可迭代对象操作方法多,但是占用内存,不能循环迭代取值,如果你侧重于数据灵活操作并且内存足够,可以使用可迭代对象
-
迭代器操作方法少,不灵活,但是可以迭代取值,取完值消失,查询速度慢
-
-
迭代器和生成器的区别:
-
迭代器都是内置函数转化过来的
-
生成器是我们自己用Python代码构建的
-
装饰器原理:
- 装饰器本质是一个函数:他要装饰一个函数,在不改变原函数的源码以及调用方式的前提下,给其增加额外的功能
- 语法糖:@index = index = test_time(index)
- 用途:
- 登录认证,打印日志,访问记录
-
最简单的装饰器函数传参:
-
def warpper(s): #s = func1 def inner(*args,**kwargs): #4-聚合接受inner的实参海洋 print(666) #执行func1函数前操作 ret = s(*args,**kwargs) #5给打散实参执行func1函数, return ret #6将func1,return执行结果传给inner return inner #2-返回inner给warpper @warpper #1-语法糖:func1 = warpper(func1) def func1(a): return f"{a}欢迎登录" print(func1("海洋")) #3-func1 = inner('海洋') 7 print结果
-
-
装饰器传参:装饰器嵌套三层函数,最外层函数接受装饰器实参,可以对形参进行操作判断
-
def wrapper(n): def wrapper1(f): def inner(*args,**kwargs): name = input("输入用户名") pwd = input("输入密码") with open(n,encoding='utf-8') as f1: #n等于语法糖传过来的值 for i in f1: j,k = i.strip().split('|') if name == j and pwd == k: ret = f(*args,**kwargs) return ret return inner return wrapper1 @wrapper('qq') #将qq传给最外层wrapper形参 def qq(): print('成功访问qq') @wrapper('weixin') def tiktok(): print('成功访问微信') qq() tiktok()
-
-
两个装饰器,装饰一个函数:先执行@wraper1 执行完的结果是@wraper2的形参。
如果两个装饰器内层函数一样,调用函数时先走最上面装饰器
-
def wrapper1(func1): # func1 = f原函数 def inner1(): print('wrapper1 ,before func') # 2 func1() print('wrapper1 ,after func') # 4 return inner1 def wrapper2(func2): # func2 == inner1 def inner2(): print('wrapper2 ,before func') # 1 func2() # inner1 print('wrapper2 ,after func') # 5 return inner2 @wrapper2 # f = wrapper2(f) 里面的f == inner1 外面的f == inner2 @wrapper1 # f = wrapper1(f) 里面的f == func1 外面的 f == inner1 def f(): print('in f') # 3 f() # inner2()
-
模块原理:
模块:
-
一个.py文件就是模块,节省代码,容易维护,组织结构更清晰
-
常用的模块:
- json,pickle:序列化,sys:路径,os :文件操作
- hashlib :加密 time datetime:时间
- random:随机取值
- 模块的两种引用方式:
- import 模块名
- from 模块名 import 变量
-
模块的运行方式:
- 脚本方式:直接用解释器执行,或者pycharm中右键运行。
-
模块方式:被其他的模块导入,为导入他的模块提供资源(变量,函数定义,)
-
模块的分类:
- 内置模块:标准库,python解释器自带的,time,os,sys,等等200多种
-
第三方库(模块):各种大神写的模块,通过pip install...安装的6000多种自己写的模块,
-
自定义模块
-
-
引用模块发生三件事:
- 1,import tbjx 将haiyang.py文件(变量,函数名)加载到内存
- 2,在内存中创建一个以太tbjx命名的名称空间
- 3,通过haiyang.xx名称空间的名字.等方式引用此模块的名字(变量,函数名)
序列化:
- 将一个数据结构(list,tuple,dict)转化成一个特殊序列的过程,并且可以翻转回去,这个转化的过程就是序列化
-
Json:
- dict,list, tuple,str,int
- 不同语言都遵循使用的一种数据转换格式,可以互相使用json传输数据
-
Pickle:
-
支持所有数据类型
python语言遵循的一种数据化转换格式,只能在python中使用
-
-
作用:
- 为什么要用序列化,因为硬盘存储和网络传输时只能接受bytes类型的。
- dumps 将数据转换 dump将数据转换并写入文件(json存储空间小,pickle存储空间大)
开发规范:
-
规范开发:文件加载问题,代码可读性差,查询麻烦
-
PEP8规范:
-
1. bin start.py 程序开关:启动代码目录,run() 2. conf settings.py 配置文件:放置一些静态参数,比如文件路径,数据库配置,软件默认设置 3. core src.py 主逻辑函数: 主要存放就是核心逻辑功能,核心函数都在这里 4. lib common.py 公共组件: 存放装饰器,密码加密功能,日志功能存放 5. db register 存放数据库文件, 注册表,用户信息 6. log access.log 存放系统的日志
-
bin start:启动start文件,工作目录已经写入到sys.path中(内存中),在这个工作目录下的文件都可以互相引用
-
import os import sys #动态获取工作目录os.path.dirname 通过file文件找到父级目录上的父级目录也就是整个代码的工作目录 BASH_PATH = os.path.dirname(os.path.dirname(__file__)) sys.path.append(BASH_PATH) from core import src if __name__ == '__main__': #防止别的文件引用执行 src.run()
-
settings:数据库地址进行拼写
-
import os BASE_PATH = os.path.dirname(os.path.dirname(__file__)) register_path = os.path.join(BASE_PATH,'db','register')
-
src:主逻辑需要引用数据库地址和装饰器文件,都需要引用
-
from conf import settings from lib import common
-
common:装饰器这块引用src中的状态和登录函数,规范其实也就是文件之间的互相引用
-
from core import src