本周总结4

异常处理

异常

异常就是代码运行报错,行业俗称叫bug
	代码运行中一旦遇到异常会直接结束整个程序的运行,我们在编写代码的过程中要尽可能的避免

异常分类

语法错误
		不允许出现,一旦出现立刻改正 
	逻辑错误
		允许出现的,因为它一眼发现不了,代码运行之后才可能会出现

常见异常错误

常见的错误:
SyntaxError:  语法错误
NameError:    名字错误
IndexError:   索引错误
KeyError :    键错误
IndentationError :缩进错误

异常处理语法结构

try:
	待检测的代码(可能会出错的代码)
except Exception as e:  # e就是系统会提示的错误类型
	针对错误类型要解决统一处理
else:
	try子代码正常运行结束没有任何报错后,在执行else子代码
finally:
	无论try的子代码是否报错,最后哦都要执行finally子代码

异常处理补充

1.断言assert
	name = 'kiki'
    # assert isinstance(name,int)
    # print('肯定是字符串')  # AssertionError
    assert  isinstance(name,str)
    print('肯定是字符串')  # 肯定是字符串

2.报错raise
	   name = 'kimi'
    if name == 'kimi':
        raise Exception('找到这里,说明我该走了')
    else:
        print('正常走')

生成器

生成器对象

1.生成器内置有__iter__和__next__方法,所以生成器本身就是一个迭代器
2.函数体代码中由yield关键字,那么函数名加括号并不会函数体代码,会生成一个生成器对象

生成器与迭代器的区别

迭代器对象是解释器自动提供的
	数据类型/文件对象>>>:迭代器对象
生成器对象是程序员编写出来的
	代码、关键字>>>:迭代器对象(生成器)

生成器的两种方法

​ yield关键字,我们就有了自定义迭代器的实现方向,yield可以用于返回值,但不同于return,函数一旦遇到return就结束了,而yield可以保存函数的运行状态挂起函数,用来返回多次值。

函数体代码中填写yield关键字
""" 1.函数体代码中如果由yield关键字,那么函数名加括号并不会执行函数体代码,会生成一个生成器对象(迭代器对象)"""
    eg:    def my_iter():  # 定义函数,先不执行
            print('奶茶真好喝')
            yield
        res = my_iter()   # 拿到生成器
  
""" 2.使用加括号之后的结果调用__next__才会执行函数体代码"""     
    eg1:    
        def my_iter():
            print('奶茶真好喝')
            yield
        res.__next__()  # 执行函数体,在yield后面停

    
""" 3.每次执行完__next__代码都会停在yield位置,下次基于这个位置继续往下找第二个yield """
""" 4.yield还有点类似于return  可以返回返回值"""
    eg2:
        def my_iter():
        print('奶茶真好喝')
        yield   110
        print('果汁真好喝')
        yield   120
        print('火锅是真香')
        yield   119
        print('烧烤也不错')
        yield    114
    res = my_iter()    # 生成生成器
    r1 = res.__next__()   # 执行到第一个yield停
    print(r1)
    r2 = res.__next__()   # 执行到第二个yield停
    print(r2)
    r3 = res.__next__()   # 执行到第三个yield停
    print(r3)
    r4 = res.__next__()   # 执行到第四个yield停
    print(r4)
 代码结果展示 :
 """   奶茶真好喝
        110
        果汁真好喝
        120
        火锅是真香
        119
        烧烤也不错
        114
                 """

生成器对象实行range方法

# 1.两个参数
def my_range(start_num,end_num):
    while start_num<end_num:
        yield start_num
        start_num+=1

for i in my_range(1,10):
    print(i)

# 2.一个参数
def my_range(start_num, end_num=None):
    if not end_num:
        end_num = start_num
        start_num = 0
        while start_num < end_num:
            yield start_num
            start_num += 1


for i in my_range(10):
    print(i)


# 3.三个参数
def my_range(start_num,end_num,step):
    while start_num<end_num:
        yield start_num
        start_num +=step

for i in my_range(1,10,2):
    print(i)



# 通用的方法
def my_range(start_num,end_num=None,step=1):
    if not end_num:
        end_num = start_num
        start_num = 0
        while start_num<end_num:
            yield start_num
            start_num +=step

for i in my_range(10):
    print(i)
    
    
    

生成器冷门用法

def func(name,python=None):
    print(f'{name}上课')
    while True:
        python = yield
        print(f'{name}正在上课{python}')
res = func('kiki')
res.__next__()
res.send('化学课')

生成器表达式

# 列表生成式
l1 = [i**2 for i in range(10)]
print(l1)


# 生成器表达式
l2 = (i*2 for i in range(10))
print(l2)
for i in l2:
    print(i)

模块

索引取值和迭代取值的差异

l1 = [11,22,33,44,55,66,77,88,99]
1.索引取值
	可以任意位置  任意次数取值
		eg:l1[2] = 33  l1[1] =22  l1[2] = 33
	不支持无序类型(如字典)的数据取值
2.迭代取值
	只能从前往后依次取值无法后退 
		eg: 11,22,33....99
	支持所有类型的数据取值(有序无序类型都可)

模块简介

​ 在python中,一个py文件就是一个模块,文件名为xxx.py模块名则是xxx,导入模块就可以使用已经写好的功能。程序中的模块可以被重复使用,既保证了代码的重用性,又增强了程序的结构和可维护性

1.模块的本质
	内部具有一定功能的py文件
2.python模块的历史
	初期被其他编程语言的程序员称为‘调包侠’,后期不得不使用python>>>:真相定律
3.python模块的表现形式
	3.1 Py文件(py文件也可以称为是模块文件)
	3.2 含有多个py文件的文件夹(按照模块功能的不同划分不同的文件夹存储)
	3.3 已被编译为共享库或DLL的C或C++扩展(了解)
	3.4 使用c编写并链接到python解释器的内置模块(了解)

模块分类

1.自定义模块
	我们自己写的模块文件
2.内置模块
	python解释器提供的模块  time
3.第三方模块
	别人写的模块文件(python背后真正的大佬)

导入模块的两种句式

1.import句式

以import aa 为例研究底层原理
	""" 
	1.先产生执行文件的名称空间
	2.执行被导入文件的代码将产生的名字放入被导入文件的名称空间中
	3.在执行文件的名称空间中产生一个模块的名字
	4.在执行文件中使用该模块名点的方式使用模块名称空间中所有的名字
import aa  # 导入模块aa
name = 'kiki'
print(aa.name)  # 打印引用模块aa中全局变量name的值
aa.func1()  # 调用模块aa中func1函数
aa.func2()  # 调用模块aa中func2的函数,等于再次调用模块aa中的func1函数
aa.change()  # 调用模块aa中change的函数,模块aa的全局变量name='kimi'修改为name='rose'
print(aa.name)
print(name)>>>>:执行文件中的全局变量name

"注意:若想要执行当前文件中的名称空间中存在的name,执行aa.get()操作的都是源文件中的全局变量name"

2.from…import…

以from...import...name,func1为例研究底层原理
	"""
	1.先产生执行文件的名称空间
	2.执行被导入文件的代码将产生对应的名字放入被导入文件的名称空间中
	3.在执行文件的名称空间中产生对应的名字绑定模块名称空间中对应的名字
	4.在执行文件中直接使用名字就可以访问名称空间中对应的名字
	
from aa import name,func1,func2,change  # 导入模块aa中的全局变量name,函数func1,func2,change
print(name) # 打印模块aa中的全局变量name的值
func1()  # 调用模块aa中func1函数
func2()  # 调用模块aa中func2函数
change()  # 调用模块aa中change函数
print(name)  # kimi
''' 
change是aa中的change,
change代码中的global name是aa全局的name,
所以不会影响执行文件的name
 '''

导入模块的句式补充

1.import与from...import....两者优缺点
	由于使用模块名称空间的名字都需要模块点的方式才可以用
		所以不会轻易的被执行文件中的名字换掉
		但是每次使用模块名称空间中的名字都必须使用模块点才可以
	from...import...句式
		指名道姓的导入模块名称空间中需要使用的名字,不需要模块点 
		但是容易跟执行文件的名字冲突(执行文件有name,导入模块也有name)
2.重复导入模块
	解释器只会导入一次,后续重复的导入语句并不会执行
	eg: import aa  # 导入模块aa
            import aa
            import aa
          '只执行导入一次'
3.起别名
	import zhongguorenming as zg
	from zhongguorenming import zhosngdeineidiedideh as f1
	from zhongguorenming import  name as n,func1 as f
	
4.涉及到多个模块导入
	如果模块相似度不高,推荐使用
    	import aa
    	import zhongguorenming	

	如果模块相似度高,推荐使用
    	import aa, zhongguorenming

循环导入问题及解决策略

1.循环导入
	两个文件之间彼此导入彼此并且相互使用各自名称空间中的名字  极容易报错
2.如何解决循环导入问题
	1.确保名字在使用之前就已经准备完毕
		name = 'from my2'  # 把name的值放在是使用之前的位置
		import my1
		print(my1.name)
	2.我们以后在编写代码的过程中尽可能避免出现循环导入

判断文件类型

所有的py文件都可以直接打印__name__对应的值
	当py文件是执行文件的时候__name__对应的值是__main__
		eg: print(__name__)  # __main__
	当py文件是被导入文件的时候__name__对应的值是模块名
		eg:import my2   # 执行文件my1 结果是my2
	
    if __name__=='__main__':  # 快捷键(敲main回车就会出来)
        print('哈哈哈,我是执行文件  我可以运行这里的子代码')
    上述脚本可以用来区分所在py文件内python代码的执行

使用场景
	1.模块开发阶段
	2.项目启动文件
	
	""" 
	执行文件里面:
	from a import *  # *默认是将模块名称空间中所有的名字导入
	被导入文件里面:
	__all__ = ['名字1','名字2']   针对*可以限制拿到的名字 
								不能拿模块中没有的名字
	
	"""

模块的查找顺序

1.内存
    import aaa
    import time

    time.sleep(5)
    print(aaa.name)
    aaa.func()
    '先从内存中中,即使加载后再删除了aaa文件,本次加载还能加载出来name,但是第二次运行之后就会报错,因为此时的aaa文件已经被删除了'
2.内置
    import time
    print(time)  # <module 'time' (built-in)>
    print(time.name)  # module 'time' has no attribute 'name'  内置time没有name的
    '以后在自定义模块的时候尽量不要与内置模块名冲突'
    
3.执行文件所在的sys.path(系统环境)
	一定要以执行文件为准!!!
	我们可以将模块所在的路径也添加到执行文件的sys.path中即可
	# import ddd
        # print(ddd.name)  # 报错  当ddd不属于当前执行文件的同级文件时需要添加绝对路径进去


	import sys
	print(sys.path)  # 列表   一般只看第一个路径
	sys.path.append(r'D:\PycharmProjects\test17\myname')
	import ddd
	print(ddd.name)  # kiki

绝对导入和相对导入

​ 绝对导入

from myname import ddd
print(ddd.name)  # kiki

from aaaa.bbbb.cccc.dddd import name  # 可以精确到变量名
print(name)  # 我是dddd文件
from aaaa.bbbb.cccc import dddd   # 也可以精确到其模块名
print(dddd.name)  # 我是dddd文件

ps:套路就是按照项目根目录一层层往下查找

​ 相对导入

. 在路径中表示当前目录
.. 在路径中表示上一层目录
..\.. 在路径中表示上上一层目录
不再依据执行文件所在的sys.path而是以模块自身路径为准
from.import b
相对导入只能基于模块文件中,不能在执行文件中使用

"""  相对导入使用频率较低,一般用绝对导入即可,结构更加清晰 """

包的概念

大白话:多个py文件的集合>>>:文件夹
专业:内部含有__init__.py文件的文件夹(python2必须要求,python3无所谓)

包的具体使用

虽然python3对包的要求降低了,不需要__init__.py也可以识别,但是为了兼容性考虑,最好还是加上__init__.py

1.如果只想用包中某几个模块,那么还是按照之前的导入方式即可
	from aaa import my1 my2
2.直接导包名
	import aaa
	导入包名其实就是导包下面的__init__.py文件,该文件内有什么名字就可以通过包点什么名字
	""" 如果单独import aaa(包名),只能导入aaa包的__init__.py文件,要是想一次性导入aaa包名下的a.py文件,提前在__init__.py中导入a.py文件"""

编程思想的转变

1.面条版阶段
	所有的代码全部堆叠在一起(if elif elif elif else)
2.函数版阶段
	根据功能的不同封装不同的函数(func_dict)
3.模块版阶段
	根据功能的不同拆分成不同的Py文件
4.面对对象

"""
第一个阶段可以看成是直接将所有的数据放在c盘
	视频  音频  文本 图片
第二个阶段可以看成是将c盘下的数据分类管理
	视频文件夹  音频文件夹  文本文件夹 图片文件夹
第三个阶段可以看成事将C盘下的数据根据功能的不同划分到更合适的位置
	系统文件夹  C盘
	视频文件夹  D盘
	图片文佳夹  E盘
	>>>>>:目的为了资源的高效管理

软件开发目录规范

软件开发目录规范

project
	bin     存放项目启动文件
		start.py   项目启动文件
	conf     项目配置文件
		settings.py  存放项目默认配置  一般全大写
	core      项目核心文件(业务逻辑相关代码)
		src.py    核心功能
	interface    项目接口文件
		user.py  根据具体业务逻辑划分对应的文件
        account.py
     db         存放相关项目数据(与数据库交互)
     	userinfo.txt
     	db_handler.py 
	lib        存放项目公共文件
		common.py    自定义文件
	log        存放项目日志文件
		log.log
	README       项目说明书
	requirements.txt   主要存放项目所需的模块和版本
	

python常用内置模块

常见的内置数据:

常见的内置数据类型:
	dict、list、set、tuple
collections模块还提供了几个数据类型:
	1.Counter     计时器,主要用来计数
	2.deque        双端队列,可以快速的从另外一侧追加和推出对象
	3.defaultdict  带有默认值的字典
	4.namedtuple   生成可以使用名字访问元素内容的tuple
	5.OrderDict    有序字典

collection模块

1.具名元组:namedtuple

eg1:表示二维坐标系
    from collections import namedtuple
    point = namedtuple('点',['x','y'])
    # 生成点的信息
    p1 = point(120,110)
    print(p1)  # 点(x=120, y=110)
    print(p1.x)  # 120
    print(p1.y)  # 110

2.deque 双端队列

队列和堆栈
	队列:先进先出
	堆栈:先进后出
队列和堆栈都是一边只能进一边只能出
队列通常是在入队时在队尾添加元素,在出队时,队头弹出元素,而双端队列没有这样的输入输出的限制.这里collections模块中的deque就是双端队列。

代码实现:

​ 使用list 存储数据时,按索引访问元素很快,但是插入和删除元素就很慢了,这个时候引入了deque,可以高效的帮助我们插入和删除列表,适合用于队列和栈


from collections import deque
q1 = deque(['a','b'])
q1.append('B')
print(q1)
q1.pop()
print(q1)
q1.appendleft('A')
print(q1)
q1.pop()
print(q1)

3.OrderedDict 有序字典

使用dict,key是无序的,在对dict做迭代时,我们无法确定key的顺序,此时我们使用collection的OrderedDict,可以保持字典的键是有序的

from collections import OrderedDict
	d = dict([('a',1),('b',2),('c',3)])
	print(d)  # {'a': 1, 'b': 2, 'c': 3}  字典的key是无序的
	d1 = OrderedDict([('a',1),('b',2),('c',3)])
	print(d1)  # OrderedDict([('a', 1), ('b', 2), ('c', 3)])  OrderedDict的key是有序的  

	注意:OrderedDict 的key会按照插入的顺序排列,不是key本身排列

4.defaultdict 默认字典

使用dict时,如果引用的Key不存在,就会抛出KeyError

如果希望key不存在时,返回一个默认值,就可以用`defaultdict

from collections import defaultdict
	dd = defaultdict(lambda: 'N/A')
	dd['key1'] = 'abc'
	dd['key1'] # key1存在
	# 'abc'
	dd['key2'] # key2不存在,返回默认值
	# 'N/A'

时间模块

三种时间表现形式
    1.时间戳 time.time()
        秒数
    2.结构化时间
        主要是给计算机看的,人看不适应
    3.格式化时间
        主要是给人看的
    Y	m	d	H	M	S	X
    年	月	日	时	分	秒	时:分:秒

time模块

# 导入时间模块
	import time

# 时间戳
	time.time()
	print(time.time())  # 1666165810.4114015

# 时间字符串
	print(time.strftime('%Y-%m-%d'))  # 2022-10-19
	print(time.strftime('%Y/%m/%d'))  # 2022/10/19
	print(time.strftime('%Y/%m/%d  %H:%M:%S'))  # 2022/10/19  15:56:52
	print(time.strftime('%Y/%m/%d  %X'))  # 2022/10/19  15:56:52

datetime模块

    import datetime
    b = datetime.datetime.now()
    print('当前日期:',b)  # 当前日期: 2022-10-19 16:16:16.266254
    print(datetime.datetime.today())  # 2022-10-19 16:17:29.847966
    print(datetime.date.today())  # 2022-10-19

随机数模块

1.导入模块

#  导入随机数
import random

2.随机小数random() uniform()

print(random.random())  #大于0小于1之间的小数 0.8705054721763096  
print(random.uniform(1,5))  # 大于1小于5的小数  1.250392711400564

3.随机整数 randint() randrange()

print(random.randint(1,6))  # 随机产生1-6之间的整数
print(random.randrange(1,100,2))  # 随机产生指定的整数1-100之间的奇数

4.随机选择一个或多个样本 choice choices sample

print(random.choice(['一等奖','二等奖','三等奖','欢迎再来']))  # 随机抽取一个样本 三等奖
print(random.choices(['一等奖','二等奖','三等奖','欢迎再来']))  # 随机抽取一个样本  ['二等奖']
print(random.sample(['kiki','kimi','rose','kevin','jerry','lili'],2))  # 随机抽取样本数 ['kimi', 'jerry']

5.打乱列表顺序

l1 = [3,5,6,9,67,4,34,97,34,'A','G','J','K','B','L']
random.shuffle(l1)
print(l1)  # 随机打乱数据集[34, 4, 'A', 67, 'L', 'G', 9, 97, 6, 5, 34, 3, 'J', 'K', 'B']

随机生成图片验证码

import random
def get_code(n):

    code = ''
    for i in range(n):
        random_upper = chr(random.randint(65,90))
        random_lower = chr(random.randint(97,122))
        random_int = str(random.randint(1,9))
        temp = random.choice([random_int,random_lower,random_upper])
        code +=temp
    return code
res = get_code(8)
print(res)

os与sys模块

os与sys模块的区别

os模块主要与操作系统打交道

sys模块主要与python解释器打交道

os模块

1.创建目录
	os.mkdir  单级
	os.makedirs  多级
	
2.删除目录
	os.rmdir
	os.removedirs
3.列举指定路径下内容
	os.listdir
4.删除或重命名
	os.remove
	os.rename
5.获取/切换当前工作目录
	os.getcwd()
	os.chdir('..')
6.动态获取项目跟路径
	os.path.abspath(__file__)
	os.path.dirname(__file__)	
7.判断路径是否存在
	os.path.exists
	os.path.isfile
	os.path.isdir
8.路径接口
	s1 
	s2
	os.path.join(s1,s2)
9.获取文件大小
os.path.getsize

sys模块

import sys
print(sys.path)  # 获取执行文件的sys.path
print(sys.getrecursionlimit())  # 获取python解释器默认最大递归深度
print(sys.setrecursionlimit(2000))  # 修改python解释器默认最大递归深度  None
print(sys.version)  # 3.8.6 (tags/v3.8.6:db45529, Sep 23 2020, 15:52:53) [MSC v.1927 64 bit (AMD64)]  查看系统版本信息
print(sys.platform)  # 平台信息 win32 (了解即可)

res = sys
if len(res) != 3:
    print('执行命令缺少了用户名或密码')
else:
    username = res[1]
    password = res[2]
    if username == 'kiki' and password == '123':
        print('kiki,您的文件正在正常执行')
    else:
        print('你不是kiki,无权执行该文件')

json模块

引入:字典转为str(字典)很简单,但是str(字典)如何转为字典呢,下面就引入了json模块,可以帮我实现这个功能。

json模块也称为序列化模块,序列化就是将原本的字典、列表等内容转换成一个字符串的过程。序列化可以打破语言限制实现不同的编程语言之间数据交互。

序列化的目的:

1.以某种存储形式是自定义对象持久化

2.将对象从一个地方传递到另一个地方

3.使程序更具维护性

json相关操作

针对数据
	json.dumps()
	json.loads()
	
针对文件
	json.dump()
	json.load()
序列化
	import json  # 引入json
方式一:dumps
	with open(r'aa.py','w',encoding='utf8') as f2:
	json_str = json.dumps(d1)  # '{}'  序列化:数据类型>>>json格式字符串
	f2.write(json_str)   # # 将序列化的文本写进文件,并以{"name": "rose", "pwd": 666}形式展示
方式二:dump
	with open(r'aa.py','w',encoding='utf8') as f2:
    	json.dump(d1,f2)  # 将数据序列化并写入文件 {"name": "rose", "pwd": 666}
反序列化
	import json  # 引入json
方式一:dumps
	with open(r'aa.py','w',encoding='utf8') as f2:
	json_str = json.dumps(d1)  # '{}'  序列化:数据类型>>>json格式字符串
	f2.write(json_str)   # # 将序列化的文本写进文件,并以{"name": "rose", "pwd": 666}形式展示
方式二:dump
	with open(r'aa.py','w',encoding='utf8') as f2:
    	json.dump(d1,f2)  # 将数据序列化并写入文件 {"name": "rose", "pwd": 666}

原文地址:http://www.cnblogs.com/zhanglanhua/p/16819616.html

1. 本站所有资源来源于用户上传和网络,如有侵权请邮件联系站长! 2. 分享目的仅供大家学习和交流,请务用于商业用途! 3. 如果你也有好源码或者教程,可以到用户中心发布,分享有积分奖励和额外收入! 4. 本站提供的源码、模板、插件等等其他资源,都不包含技术服务请大家谅解! 5. 如有链接无法下载、失效或广告,请联系管理员处理! 6. 本站资源售价只是赞助,收取费用仅维持本站的日常运营所需! 7. 如遇到加密压缩包,默认解压密码为"gltf",如遇到无法解压的请联系管理员! 8. 因为资源和程序源码均为可复制品,所以不支持任何理由的退款兑现,请斟酌后支付下载 声明:如果标题没有注明"已测试"或者"测试可用"等字样的资源源码均未经过站长测试.特别注意没有标注的源码不保证任何可用性