首页 > 其他分享 >第三周总结

第三周总结

时间:2022-10-16 22:12:47浏览次数:40  
标签:总结 index 函数 res 第三周 time print def

文件操作

利用python代码的编写来读写文件

1.文件的概念

就是操作系统暴露给用户操作硬盘的快捷方式
eg:双击一个文件 其实是从硬盘将数据加载到内存
ctrl+s保存文件 其实是将内存中的数据刷到硬盘保存

2.文件的操作方式

代码打开文件的两种方式
方式1:
f = open(文件路径,读写模式,encoding='utf8')
f.close()
方式2:
with open('a.txt', 'r', encoding='utf8') as f1:
    with子代码块
ps:with上下文管理好处在于子代码运行结束自动调用close方法关闭资源
"""
open方法的第一个参数是文件路径 并且撬棍跟一些字母的组合会产生特殊的含义导致路径查找混乱 为了解决该问题可以在字符串的路径前面加字母r
	D:\a\n\t
	r'D:\a\n\t'
以后涉及到路径的编写 推荐加上r
with支持一次性打开多个文件
	with open() as f1,open() as f2,open() as f3:
		子代码
"""

3.文件读写模式

'r'		只读模式:只能读不能写
    # 1.文件路径不存在:会直接报错
    with open(r'b.txt','r',encoding='utf8') as f:
        print(f.read())
    # 2.文件路径存在:正常读取文件内容
    with open(r'a.txt', 'r', encoding='utf8') as f:
        print(f.read())

'w'		只写模式:只能写不能看
    # 1.文件路径不存在:自动创建
    with open(r'b.txt', 'w', encoding='utf8') as f:
        pass
    # 2.文件路径存在:先清空文件内容 之后再写入
    with open(r'a.txt', 'w', encoding='utf8') as f:
        f.write('假期综合征 赶紧要调整\n')
        f.write('假期综合征 赶紧要调整\n')
        f.write('假期综合征 赶紧要调整\n')
    '''强调:换行符需要自己添加 并且在后续数据读取比对的时候也一定要注意它的存在'''

'a'		只追加模式:文件末尾添加数据
    # 1.文件路径不存在:自动创建
    with open(r'c.txt', 'a', encoding='utf8') as f:
        pass
    # 2.文件路径存在:自动在末尾等待追加内容
    with open(r'a.txt', 'a', encoding='utf8') as f:
        f.write('放假七天和上班七天感觉是完全不一样的')

"""
当我们在编写代码的时候 有些部分不知道写什么具体代码 但是也不能空着不写
这个时候可以使用关键字
	pass
	...
只补全语法不执行功能 本身没有任何的含义
"""

4.文件操作模式

t	文本模式
	默认的模式 我们上面所写的r w a其实全称是 rt wt at
	1.只能操作文本文件
 	2.读写都是以字符为单位
  	3.需要指定encoding参数 如果不知道则会采用计算机默认的编码

b	二进制模式(bytes模式)
	不是默认的模式 需要自己指定 rb wb ab
 	1.可以操作任意类型的文件
 	2.读写都是以bytes为单位
 	3.不需要指定encoding参数 因为它已经是二进制模式了 不需要编码

二进制模式与文本模式针对文件路径是否存在的情况下 规律是一样的!!!

5.文件诸多方法

1.read()
	一次性读取文件内容 并且光标停留在文件末尾 继续读取则没有内容
	并且当文件内容比较多的时候 该方法还可能会造成计算机内存溢出
 	括号内还可以填写数字 在文本模式下 表示读取几个字符
2.for循环
	一行行读取文件内容 避免内存溢出现象的产生
3.readline()
	一次只读一行内容
4.readlines()
	一次性读取文件内容 会按照行数组织成列表的一个个数据值
5.readable()
	判断文件是否具备读数据的能力
6.write()
	写入数据
7.writeable()
	判断文件是否具备写数据的能力
8.writelines()
	接收一个列表 一次性将列表中所有的数据值写入
9.flush()
	将内存中文件数据立刻刷到硬盘 等价于ctrl + s

6.文件内容修改

# 文件a.txt内容如下
张一蛋     山东    179    49    12344234523
李二蛋     河北    163    57    13913453521
王全蛋     山西    153    62    18651433422

# 执行操作
with open('a.txt', 'r+', encoding='utf8') as f:
    f.seek(9)
    f.write('<妇女主任>')
# 文件修改后的内容如下
张一蛋<妇女主任> 179    49    12344234523
李二蛋     河北    163    57    13913453521
王全蛋     山西    153    62    18651433422

# 强调:
# 1、硬盘空间是无法修改的,硬盘中数据的更新都是用新内容覆盖旧内容
# 2、内存中的数据是可以修改的

文件内容修改方式:
方式1:覆盖写
优点: 在文件修改过程中同一份数据只有一份
缺点: 会过多地占用内存

with open(r'a.txt', 'r', encoding='utf8') as f:
    data = f.read()
with open(r'a.txt', 'w', encoding='utf8') as f1:
    f1.write(data.replace('jason', 'qyf'))

方式2:换地写
优点: 不会占用过多的内存
缺点: 在文件修改过程中同一份数据存了两份

'''先在另外一个地方写入内容 然后将源文件删除 将新文件命名成源文件'''
import os
with open('a.txt', 'r', encoding='utf8') as read_f, \
        open('.a.txt.swap', 'w', encoding='utf8') as write_f:
    for line in read_f:
        write_f.write(line.replace('qyf', 'qyfnp'))


os.remove('a.txt')  # 删除a.txt
os.rename('.a.txt.swap', 'a.txt')  # 重命名文件

7.文件光标移动

with open(r'a.txt', 'rb') as f:
    print(f.read())
    f.seek(0,0)
    print(f.read())
    f.seek(0, 0)
    print(f.read())
    # print(f.read(2).decode('utf8'))
    # f.seek(-1, 2)
    # print(f.tell())  # 返回光标距离文件开头产生的字节数
    """
    seek(offset, whence)
        offset是位移量 以字节为单位
        whence是模式   0  1  2
            0是基于文件开头
                文本和二进制模式都可以使用
            1是基于当前位置
                只有二进制模式可以使用
            2是基于文件末尾
                只有二进制模式可以使用
    """
    # print(f.read(3).decode('utf8'))
文件内光标移动实战案列(了解)
import time
with open(r'a.txt', 'rb') as f:
    f.seek(0, 2)
    while True:
        line = f.readline()
        if len(line) == 0:
            # 没有内容
            time.sleep(0.5)
        else:
            print(line.decode('utf8'), end='')

函数

函数前戏

name_list = ['jason', 'kevin', 'oscar', 'jerry']
# print(len(name_list))
'''突然len不准用了'''
# count = 0
# for i in name_list:
#     count += 1
# print(count)
'''统计列表内数据值个数的代码需要在很多地方使用'''
# 相同的代码需要在不同的位置反复执行
"""
循环
    相同的代码在相同的位置反复执行
函数
    相同的代码在不同的位置反复执行
ps:相同的代码不是真正一模一样而是可以通过传入的数据不同而做出不同的改变
"""
def my_len():
    count = 0
    for i in name_list:
        count += 1
    print(count)
my_len()
"""
函数相当于是工具(具有一定功能)
    不用函数
        修理工需要修理器件要用锤子 原地打造 每次用完就扔掉 下次用继续原地打造
    用函数
        修理工提前准备好工具 什么时候想用就直接拿出来使用
"""

函数的语法结构

def 函数名(参数):
	'''函数注释'''
	函数体代码
	return 返回值
1.def
	定义函数的关键字
2.函数名
	命名等同于变量名
3.参数
	可有可无 主要是在使用函数的时候规定要不要外界传数据进来
4.函数注释
	类似于工具说明书
5.函数体代码
	是整个函数的核心 主要取决于程序员的编写
6.return
	使用函数之后可以返回给使用者的数据 可有可无

函数的定义与调用

1.函数在定义阶段只检测语法 不执行代码
	def func():
		pass
2.函数在调用阶段才会执行函数体代码
	func()
3.函数必须先定义后调用
4.函数定义使用关键字def函数调用使用>>>:函数名加括号
	如果有参数则需要在括号内按照相应的规则传递参数(后续详细解释)

函数的分类

1.空函数
	函数体代码为空 使用的pass或者...补全的
	空函数主要用于项目前期的功能框架搭建
	def register():
	"""注册功能"""
		pass
2.无参函数
	定义函数的时候括号内没有参数
	def index():
		print('from index function')
3.有参函数
	定义函数的时候括号内写参数 调用函数的时候括号传参数
	def func(a):
		print(a)

函数的返回值

1.什么是返回值
	调用函数之后返回给调用者的结果
2.如何获取返回值
	变量名 赋值符号 函数的调用
 	res = func()  # 先执行func函数 然后将返回值赋值给变量res
3.函数返回值的多种情况
	3.1.函数体代码中没有return关键字 默认返回None
 	3.2.函数体代码有return 如果后面没有写任何东西还是返回None
 	3.3.函数体代码有return 后面写什么就返回什么
 	3.4.函数体代码有return并且后面有多个数据值 则自动组织成元组返回
 	3.5.函数体代码遇到return会立刻结束

函数的参数

形式参数
	在函数定义阶段括号内填写的参数 简称'形参'
实际参数
	在函数调用阶段括号内填写的参数 简称'实参'
***************************************************
"""
形参与实参的关系
	形参类似于变量名 在函数定义阶段可以随便写 最好见名知意
	def register(name,pwd):
		pass

	实参类似于数据值 在函数调用阶段与形参临时绑定 函数运行结束立刻断开
	register('jason',123)   形参name与jason绑定 形参pwd与123绑定
"""
***************************************************

位置参数

位置形参
	函数定义阶段括号内从左往右依次填写的变量名
	def func1(a, b, c):pass
"""
补充:当子代码只有一行并且很简单的情况下 可以直接在冒号后编写 不要换行
"""
位置实参
	函数调用阶段括号内从左往右依次填写的数据值
    func1(1, 2, 3)

def func1(a, b):
    print(a, b)

func1(1, 2)  # 按照位置一一对应传值
func1(1)  # 少一个不行会报错
func1(1, 2, 3)  # 多一个也不行也会报错
func1(b=1, a=2)  # 关键字传参(指名道姓的传)
func1(b=1, 2)  # 关键字传参一定要跟在位置传参的后面 报错
func1(2, b=1)  # 可以
func1(1, a=2, b=3)  # 同一个形参在调用的时候不能多次赋值
name = 'qyf'
pwd = 123
funcl(name, pwd)  # 实参没有固定的定义 可以传数据值 也可以传绑定了数据值的变量名
func1(a=name, b=pwd)  # 实参没有固定的定义 可以传数据值 也可以传绑定了数据值的变量名
"""
越短的越简单的越靠前
越长的越复杂的越靠后
但是遇到下列的情况除外
	同一个形参在调用的时候不能多次赋值
"""

默认参数

本质其实就是关键字形参(指定有默认值的形式参数必须在所有没默认值参数的最后,否则会产生语法错误)
	别名叫默认参数:提前就已经给了 用户可以不传 也可以传
"""
默认参数的定义也遵循短的简单的靠前 长的复杂的靠后
"""
def register(name, age, gender='male'):
    print(f"""
    --------学员信息--------
    姓名:{name}
    年龄:{age}
    性别:{gender}
    ----------------------
    """)


register('qyf', 18)
register('wei', 23, 'female')
register('lili', 34, gender='female')

可变长参数

可变长形参

def func1(*a):
    print(a)


func1()  # ()
func1(1)  # (1,)
func1(1, 2)  # (1, 2)


def func2(b, *a):
    print(a, b)


func2()  # 报错 函数至少需要一个参数给到b
func2(1)  # () 1
func2(1, 2, 3, 4)  # (2, 3, 4) 1
"""
*号在形参中
	用于接受多余的位置参数 组织成元组赋值给*号后面的变量名
"""
def func3(**k):
    print(k)


func3()  # {}
func3(a=1)  # {'a': 1}
func3(a=1, b=2, c=3)  # {'a': 1, 'b': 2, 'c': 3}


def func4(a, **k):
    print(a, k)


func4()  # 报错 函数至少需要一个参数给到a
func4(a=1)  # 1 {}
func4(a=1, b=2, c=3)  # 1 {'b': 2, 'c': 3}
func4(a=1, b=2, c=3, x='qyf', y='wei')  # 1 {'b': 2, 'c': 3, 'x': 'qyf', 'y': 'wei'}
"""
**号在形参中
	用于接收多余的关键字参数 组织成字典的额形式赋值给**号后面的变量名
"""
def func5(*a, **k):
    print(a, k)


func5()  # () {}
func5(1, 2, 3)  # (1, 2, 3) {}
func5(a=1, b=2, c=3)  # () {'a': 1, 'b': 2, 'c': 3}
func5(1, 2, 3, a=1, b=2, c=3)  # (1, 2, 3) {'a': 1, 'b': 2, 'c': 3}


def func5(n, *a, **k):
    print(n, a, k)


# func5()  # 报错 函数至少需要一个参数给到n
func5(1, 2, 3)  # 1 (2, 3) {}
func5(111, a=1, b=2, c=3)  # 111 () {'a': 1, 'b': 2, 'c': 3}
func5(n=111, a=1, b=2, c=3)  # 111 () {'a': 1, 'b': 2, 'c': 3}
func5(a=1, b=2, c=3, n=111)  # 111 () {'a': 1, 'b': 2, 'c': 3}
func5(1, 2, 3, a=1, b=2, c=3)  # 1 (2, 3) {'a': 1, 'b': 2, 'c': 3}
"""
由于*和**在函数的形象中使用频率很高 后面跟的变量名推荐使用
	*args
	**kwargs
def index(*args, **kwargs):pass
"""

可变长实参

def index(a, b, c):
    print(a, b, c)


l1 = [11, 22, 33]
t1 = (11, 22, 33)
s1 = 'qyf'
se = {123, 231, 222}
d1 = {'username': 'qyf', 'pwd': 123, 'age': 23}
'''将列表中三个数据值取出来传给函数的三个形参'''
index(*l1)  # 11 22 33
index(*t1)  # 11 22 33
index(*s1)  # q y f
index(*se)  # 123 222 231 集合本身就是无序的
index(*d1)  # username pwd age
"""
*在实参中
	类似于for循环 将所有循环遍历出来的数据按照位置参数一次性传给函数
"""
def index(username, pwd, age):
    print(username, pwd, age)


d1 = {'username': 'qyf', 'pwd': 123, 'age': 23}
index(username=d1.get('username'), pwd=d1.get('pwd'), age=d1.get('age'))  # qyf 123 23
index(**d1)  # qyf 123 23
"""
**在实参中
	将字典打散成关键字参数的形式传递给函数
"""
def index(*args, **kwargs):
    print(args)  
    print(kwargs)  


index(*[11, 22, 33, 44], x=3, y=4)  # (11, 22, 33, 44) {'x': 3, 'y': 4}
index(*(11, 22, 33, 44))  # (11, 22, 33, 44) {}

命名关键字参数(了解)

'''形参必须按照关键字参数传值>>>:命名关键字参数'''


def index(name, *args, gender='male', **kwargs):
    print(name, args, gender, kwargs)


index('qyf', 1, 2, 3, 4, a=1, b=2)  # qyf (1, 2, 3, 4) male {'a': 1, 'b': 2}
index('qyf', 1, 2, 3, 4, 'female', b=2)  # qyf (1, 2, 3, 4, 'female') male {'b': 2}

名称空间

"""
name = 'qyf'
1.申请内存空间存储qyf
2.给qyf绑定一个变量名name
3.后续通过变量名name就可以访问到qyf
"""
名称空间就是用来存储变量名与数据值绑定关系的地方(我们也可以简单的理解为就是存储变量名的地方)
1.内置名称空间
	解释器运行自动产生 里面包含了很多名字 
		eg:len print input
            
2.全局名称空间
	py文件运行产生 里面存放文件级别的名字
		name = 'jason'

		if name:
			age = 18

		while True:
			gender = 'male'


		def index():
			pass

		class MyClass(object):
			pass
	name\age\gender\index\MyClass都在全局名称空间
    
3.局部名称空间
	函数体代码运行\类体代码运行 产生的空间

存活周期

存活周期
	内置名称空间
  		python解释器启动则创建 关闭则销毁
 	全局名称空间
    	py文件执行则创建 运行结束则销毁
 	局部名称空间
    	函数体代码运行创建 函数体代码结束则销毁(类暂且不考虑)

作用范围(域)

	内置名称空间
    	解释器级别的全局有效
 	全局名称空间
    	py文件级别的全局有效
 	局部名称空间
    	函数体代码内有效

名字的查找顺序

涉及到名字的查找 一定要先搞明白自己在哪个空间
1.当我们在局部名称空间中的时候
	局部名称空间 >>> 全局名称空间 >>> 内置名称空间
2.当我们在全局名称空间中的时候
	全局名称空间 >>> 内置名称空间
ps:其实名字的查找顺序是可以打破的 

查找顺序案例

1.相互独立的局部名称空间默认不能够互相访问
	def func1():、
		name = 'jason'
		print(age)

	def func2():
		age = 18
		print(name)
2.局部名称空间嵌套
	先从自己的局部名称空间查找 之后由内而外依次查找
"""
函数体代码中名字的查找顺序在函数定义阶段就已经固定死了
	x = '干饭了'
    def func1():
        x = 1
        def func2():
            x = 2
            def func3():
                x = 3
                print(x)
            func3()
        func2()

    func1()
"""

global与nonlocal

money = 666


def index():
    global money
    money = 123


index()
print(money)  # 123
"""
global局部名称空间直接修改全局名称空间中的数据
"""
def index():
    name = 'qyf'

    def inner():
        nonlocal name
        name = 'wei'

    inner()
    print(name)


index()  # wei
"""
nonlocal内层局部名称空间修改外层局部名称空间中的数据
"""

函数名的多种用法

函数名绑定的也就是一块内存地址 只不过该地址里面存放的不是数据值而是一段代码 函数名加括号就会找到该代码并执行
1.可以当作变量名赋值
def index(): pass
res = index  # 将index的内存地址赋值给变量名res
res()  # res()等于调用index函数下的函数体代码
2.可以当做函数的参数
def index():
    print('from index')
def func(a):  # 将index内存地址赋值给a
    print(a)  # 打印a也就是打印index的内存地址
    a()  # 等于调用index函数 运行index下函数体代码
func(index)  # 调用func函数传参数index
3.可以当作函数的返回值
def index():
    print('from index')
def func():
    print('from func')
    return index
res = func()  # 调用func函数 执行打印并将index的内存地址返回并赋值给res
print(res)  # 打印index内存地址
res()  # 等于调用index函数体代码
def index():
    print('from index')
    def func():
        print('from func')
    return func
res = index()  # 先调用index函数 执行打印并将返回的func内存地址赋值给res
print(res)  # 打印func内存地址
res()  # 等于调用func函数体代码
4.可以当做容器类型(可以存放多个数据的数据类型)的数据
def register():
    print('注册功能')
def login():
    print('登录功能')
def withdraw():
    print('提现功能')
def transfer():
    print('转账功能')
def shopping():
    print('购物功能')
# 定义功能编号与功能的对应关系
fun_dict = {
    '1': register,
    '2': login,
    '3': withdraw,
    '4': transfer,
    '5': shopping
}
while True:
    print("""
    1.注册功能
    2.登录功能
    3.提现功能
    4.转账功能
    5.购物功能
    """)
    choice = input('输入编号>>>:').strip()
    if choice in fun_dict:
        fun_name = fun_dict.get(choice)
        fun_name()
    else:
        print('没有此功能编号')

闭包函数

"""
定义在函数内部的函数 并且用到了外部函数名称空间中的名字
1.定义在函数内的内容
2.用到外部函数名称空间中的名字
"""
def index()
	name = 'qyf'
	def inner():
		print(name)
闭包函数实际应用>>>:是另外一种给函数体代码传参的方式
给函数体代码传参的方式1:代码里面缺什么变量名 
                 形参里面就补什么变量名
def register(name, age):
    print(f"""
    姓名:{name}
    年龄:{age}
    """)
register('qyf', 23)
给函数体代码传参的方式2:闭包函数
def outer(name, age):
    def register():
        print(f"""
        姓名:{name}
        年龄:{age}
        """)
    return register
res = outer('qyf', 23)
res()
res = outer('wei', 23)
res()

装饰器

装饰器简介

1.概念
在不改变被装饰对象原代码和调用方式的情况下给被装饰对象添加新的功能
2.本质
并不是一门新的技术 而是由函数参数、名称空间、函数名多种用法、闭包函数组合到一起的结果
3.口诀
对修改封闭 对拓展开放
4.储备知识
时间相关操作
import time
print(time.time())  # # 时间戳(距离1970-01-01 00:00:00所经历的秒数)
time.sleep(3)  # 3秒后执行后面的代码
print('666')

count = 0
# 循环之前先获取时间戳
start_time = time.time()
while count < 5000:
    print('拜拜了你咧')
    count += 1
end_time = time.time()  # 循环结束后再次获取时间戳
print('循环消耗的时间:', end_time - start_time)

装饰器推导流程图

import time
def index():
    time.sleep(3)
    print('from index')
def home():
    time.sleep(1)
    print('from home')
"""1.直接在调用index函数的前后添加代码"""
start_time = time.time()
index()
end_time = time.time()
print('函数index的执行时间为>>>:', end_time - start_time)
"""2.index调用的地方较多 代码不可能反复拷贝>>>:相同的代码需要在不同的位置反复执行>>>:函数"""
def get_time():
    start_time = time.time()
    index()
    end_time = time.time()
    print('函数index的执行时间为>>>:', end_time - start_time)
get_time()
"""3.函数体代码写死了 只能统计index的执行时间
    如何能做到统计更多的函数运行时间 
    直接传参变换统计的函数"""
def get_time(func):
    start_time = time.time()
    func()
    end_time = time.time()
    print('函数的执行时间为>>>:', end_time - start_time)
get_time(index)
get_time(home)
"""4.虽然实现了一定的兼容性 但是并不符合装饰器的特征 第一种传参不合适 只能考虑闭包函数"""
def outer(func):
    def get_time():
        start_time = time.time()
        func()
        end_time = time.time()
        print('函数的执行时间为>>>:', end_time - start_time)
    return get_time
res = outer(index)
res()
res1 = outer(home)
res1()
"""5.调用方式还是改变了 并不满足装饰器特征
    如何变形>>>:变量名赋值绑定(***********)"""
def outer(func):
    def get_time():
        start_time = time.time()
        func()
        end_time = time.time()
        print('函数的执行时间为>>>:', end_time - start_time)
    return get_time
index = outer(index)  # 赋值符号的左边是一个变量名可以随意命名
home = outer(home)
index()
home()
"""6.上述装饰器只能装饰无参函数 兼容性太差"""
import time
def index(a):
    time.sleep(3)
    print('from index', a)
def home(a, b):
    time.sleep(1)
    print('from home', a, b)
def outer(func):
    def get_time(a, b):
        start_time = time.time()
        func(a, b)
        end_time = time.time()
        print('函数的执行时间为>>>:', end_time - start_time)
    return get_time
index = outer(index)
home = outer(home)
# index(1)  # 报错
home(1, 2)
"""7.被装饰的函数不知道有没有参数以及有几个参数
    如何兼容"""
import time
def index(a):
    time.sleep(3)
    print('from index', a)
def home(a, b):
    time.sleep(1)
    print('from home', a, b)
def short():
    time.sleep(2)
    print('from short')
def outer(func):
    def get_time(*args, **kwargs):
        start_time = time.time()
        func(*args, **kwargs)
        end_time = time.time()
        print('函数的执行时间为>>>:', end_time - start_time)
    return get_time
index = outer(index)
home = outer(home)
short = outer(short)
index(1)
home(1, 2)
short()
"""8.如果被装饰的函数有返回值"""
import time
def index(a):
    time.sleep(3)
    print('from index', a)
    return 'index'
def home(a, b):
    time.sleep(1)
    print('from home', a, b)
    return 'home'
def short():
    time.sleep(2)
    print('from short')
    return 'short'
def outer(func):
    def get_time(*args, **kwargs):
        start_time = time.time()
        res = func(*args, **kwargs)
        end_time = time.time()
        print('函数的执行时间为>>>:', end_time - start_time)
        return res
    return get_time
index = outer(index)
home = outer(home)
short = outer(short)
res = index(1)
print(res)
res = home(1, 2)
print(res)
res = short()
print(res)

有参装饰器

# 校验用户是否登录装饰器
def outer(mode):
    def login_auth(func_name):
        def inner(*args, **kwargs):
            username = input('username>>>:').strip()
            password = input('password>>>:').strip()
            if mode == '1':
                print('跟定义好的结果比对 数据值直接写死')
            elif mode == '2':
                print('打开文本文件 一行行读取比对')
            elif mode == '3':
                print('跟提前定义好的字典 比对')
            elif mode == '4':
                print('数据来源于MySQL')
        return inner
    return login_auth
"""当装饰器中需要额外的参数时>>>:有参装饰器"""
"""
函数名加括号执行优先级最高 有参装饰器的情况
    先看函数名加括号的执行
    然后再是语法糖的操作
"""
@outer('1')
def index():
    print('from index')
index()
@outer('2')
def func():
    print('from func')
func()

装饰模板器

# 最常用的无参装饰器
def outer(func_name):
    def inner(*args, **kwargs):
        res = func_name(*args, **kwargs)
        return res
    return inner
@outer
def index():
    pass

# 不常用的有参装饰器
def outer_plus(mode):
    def outer(func_name):
        def inner(*args, **kwargs):
            res = func_name(*args, **kwargs)
            return res
        return inner
    return outer
@outer_plus('MySQL')
def func():
    pass

装饰器修复技术

from functools import wraps  # 修复技术固定代码
def outer(func_name):
    @wraps(func_name)  # 仅仅是为了让装饰器的效果更加逼真
    def inner(*args, **kwargs):
        """我是inner 我擅长让人蒙蔽"""
        res = func_name(*args, **kwargs)
        return res
    return inner

@outer
def func():
    """我是真正的func 我很强大 我很牛 我很聪明"""
    pass


help(func)
print(func) 

装饰器语法糖

def outer(func_num):
    def inner(*args, **kwargs):
        print('执行被装饰对象之前要做的额外操作')
        res = func_num(*args, **kwargs)
        print('执行被装饰对象之后要做的额外操作')
        return res
    return inner
"""
语法糖会自动将下面紧挨着的函数名当作第一个参数自动传给@函数调用
"""
@outer  # func = outer(func)
def func():
    print('from func')
    return 'func'

@outer  # index = outer(index)
def index():
    print('from index')
    return 'index'
func()
index()

多层语法糖

多层语法糖>>>:加载顺序由下而上

每次执行之后如果上面还有语法糖 则直接将返回值函数名传给上面的语法糖

如果上面没有语法糖了 则变形 index = outer1(wrapper2)

def outer1(func1):  # func1 = wrapper2
    print('加载了outer1')
    def wrapper1(*args, **kwargs):
        print('执行了wrapper1')
        res1 = func1(*args, **kwargs)
        return res1
    return wrapper1

def outer2(func2):  # func2 = wrapper3
    print('加载了outer2')
    def wrapper2(*args, **kwargs):
        print('执行了wrapper2')
        res2 = func2(*args, **kwargs)
        return res2
    return wrapper2

def outer3(fun3):  # func3 = index
    print('加载了outer3')
    def wrapper3(*args, **kwargs):
        print('执行了wrapper3')
        res3 = fun3(*args, **kwargs)
        return res3
    return wrapper3


@outer1  # index = outer1(wrapper2) 返回值是wrapper1
@outer2  # outer2(wrapper3) 返回值是wrapper2
@outer3  # outer3(index函数) 返回值是wrapper3
def index():
    print('666')

index()

image

递归函数

1.函数的递归调用
函数直接或者间接的调用了函数自身
直接调用
def index():
    print('from index')
    index()
index()
间接
def index():
    print('from index')
    func()

def func():
    print('from func')
    index()

func()
'''最大递归深度:python解释器添加的安全措施'''
count = 0
def index():
    global count
    count += 1
    print(count)
    index()
index()
'''官网提供的最大递归深度为1000 我们在测试的时候可能会出现996 997 998'''

2.递归函数
1.直接或者间接调用自己
2.每次调用都必须比上一次简单
  并且需要有一个明确的结束条件
递推: 一层层往下
回溯: 基于明确的结果一层层往上
"""
get_age(5) = get_age(4) + 2
get_age(4) = get_age(3) + 2
get_age(3) = get_age(2) + 2
get_age(2) = get_age(1) + 2
get_age(1) = 18
"""


def get_age(n):
    if n == 1:
        return 18
    return get_age(n - 1) + 2


res = get_age(5)
print(res)

算法简介

1.什么是算法
	算法就是解决问题的有效方法 不是所有的算法都很高效也有不合格的算法
2.算法应用场景
	推荐算法(抖音视频推送 淘宝商品推送)
	成像算法(AI相关)......
	几乎涵盖了我们日常生活中的方方面面

img

二分法

二分法就是通过每次取中间位置与目标比较,每次可以缩小一半寻找范围的寻找方法

"""
二分法使用要求
	待查找的我数据集必须有序
二分法的缺陷
	针对开头结尾的数据 查找效率很低
"""
l1 = [11, 22, 33, 44, 55, 66, 77, 88, 99, 200, 333, 555, 777, 999, 3333, 11111, 22222]
# 查找列表中某个数据值
# 方式1:for循环 次数较多
# 方式2:二分法 不断的对数据集做二分切割
"""代码实现二分法"""
def get_middle(l1, target_num):
    # 添加一个结束条件
    if len(l1) == 0:
        print('很抱歉没找到')
        return
    # 1.获取列表中间索引值
    middle_index = len(l1) // 2
    # 2.比较目标数据值与中间索引值的大小
    if target_num > l1[middle_index]:
        # 切片保留列表左边一半
        right_l1 = l1[middle_index + 1:]
        print(right_l1)
        # 针对右边一半的列表继续二分并判断>>>:得用递归函数
        return get_middle(right_l1, target_num)
    elif target_num < l1[middle_index]:
        # 切片保留列表左边一半
        left_l1 = l1[:middle_index]
        print(left_l1)
        # 针对左边一半的列表继续二分并判断>>>:得用递归函数
        return get_middle(left_l1, target_num)
    else:
        print('恭喜你 找到了!!!')
get_middle(l1, 44)
get_middle(l1, 3333)

生成式/表达式/推导式

三元表达式

语法格式为:数据值1 if 条件 else 数据值2

简化步骤1:代码简单并且只有一行 那么可以直接在冒号后面编写
name = 'qyf'
if name == 'qyf':print('大哥')
else:print('弟弟')
"""三元表达式"""
res = '大哥' if name == 'qyf' else '弟弟'
print(res)  # 大哥
"""
条件成立则使用数据值1 条件不成立则使用数据值2
当结果是二选一的情况下 使用三元表达式较为简便
并且不推荐多个三元表达式嵌套
"""

列表生成式

name_list = ['jason', 'kevin', 'tony', 'tom', 'jerry']
给列表中所有人名的后面加上_NB的后缀
for循环
new_list = []
for name in name_list:
    data = f'{name}_NB'
    new_list.append(data)
print(new_list)
列表生成式
先看for循环 每次for循环之后再看for关键字前面的操作
new_list = [name + '_NB' for name in name_list]
print(new_list)
复杂情况
new_list = [name + '_NB'for name in name_list if name == 'jason']
print(new_list)  # ['jason_NB']
new_list = ['大佬' if name == 'jason' else '小赤佬' for name in name_list if name != 'jerry']
print(new_list)  # ['大佬', '小赤佬', '小赤佬', '小赤佬']

字典生成式

enumerate(iteration, start)函数默认包含两个参数,其中iteration参数为需要遍历的参数,比如字典、列表、元组等,start参数为开始的参数,默认为0(不写start那就是从0开始)。enumerate函数有两个返回值,第一个返回值为从start参数开始的数,第二个参数为iteration参数中的值。

s1 = 'hello world'
for i,j in enumerate(s1, start=100):
    print(i,j)
# 100 h
# 101 e
# 102 l
# 103 l
# 104 o
# 105  
# 106 w
# 107 o
# 108 r
# 109 l
# 110 d
d1 = {i:j for i, j in enumerate(s1)}
print(d1)  # {0: 'h', 1: 'e', 2: 'l', 3: 'l', 4: 'o', 5: ' ', 6: 'w', 7: 'o', 8: 'r', 9: 'l', 10: 'd'}

集合生成式

res = {i + 'lowb' for i in 'hello'}
print(res)  # {'olowb', 'elowb', 'llowb', 'hlowb'}

元组生成式

元组生成式>>>:没有元组生成式 下列的结果是生成器(后面讲)
res = (i+'SB' for i in 'hello')
print(res)  # <generator object <genexpr> at 0x0000020FEDA6AD60>
for i in res:
    print(i)
# hSB
# eSB
# lSB
# lSB
# oSB

匿名函数

没有名字的函数 需要使用关键字lambda
语法结构
	lambda 形参:返回值
使用场景
	lambda a,b:a+b
匿名函数一般不单独使用 需要配合其他函数一起用

内置函数

重要内置函数

1.map()	映射
l1 = [1, 2, 3, 4, 5]
# def func(a):
#     return a + 1
res = map(lambda x: x + 1, l1)
print(list(res))  # [2, 3, 4, 5, 6]


2.max()\min()
l1 = [11, 22, 33, 44]
res = max(l1)
print(res)  # 44
d1 = {
    'zja': 100,
    'zjson': 8888,
    'berk': 99999999,
    'oscar': 1
}
print(max(d1))  # zjson  只有键参与   65~90为A~Z  97~122为a~z

def func(a):
    return d1.get(a)
res = max(d1, key=lambda k: d1.get(k))
print(res)  # berk

res = max(d1, key=func)
print(res)  # berk 调用函数func按键取值  值比大小后返回最大值所对应的键

3.reduce
reduce  传多个值 返回一个值
from functools import reduce
l1 = [11, 22, 33, 44, 55, 66, 77, 88]
res = reduce(lambda a, b: a + b, l1)  # 11+22=33 33+33=66 66+44=110....
print(res) # 396
zip()
将可迭代的对象作为参数,将对象中对应的元素打包成一个个元组,然后返回由这些元组组成的对象,一般会用listuo输出为列表
利用 * 号操作符,可以将元组解压为列表
l1 = [11, 22, 33, 44, 55]
l2 = ['jason', 'kevin', 'oscar', 'jerry', 'tony']
l3 = [1, 2, 3, 4, 5]
res = zip(l1, l2, l3)
print(list(res))  # [(11, 'jason', 1), (22, 'kevin', 2), (33, 'oscar', 3), (44, 'jerry', 4), (55, 'tony', 5)]
l1 = [11, 22, 33]
l2 = ['jason', 'kevin', 'oscar', 'jerry', 'tony']
l3 = [1, 2, 3, 4]
res = zip(l1, l2, l3)
print(list(res))  # [(11, 'jason', 1), (22, 'kevin', 2), (33, 'oscar', 3)]
filter()
用于过滤序列,过滤掉不符合条件的元素,返回一个迭代器对象,如果要转换为列表,可以使用 list() 来转换
l1 = [11, 22, 33, 44, 55, 66, 77, 88]
res = filter(lambda x: x > 40, l1)
print(list(res))  # [44, 55, 66, 77, 88]
sorted()
sort 与 sorted 区别:
sort 是应用在 list 上的方法,sorted 可以对所有可迭代的对象进行排序操作。
list 的 sort 方法返回的是对已经存在的列表进行操作,而内建函数 sorted 方法返回的是一个新的 list,而不是在原来的基础上进行的操作
l1 = [21, 12, 53, 64, 76, 32, 11, 22]
res = sorted(l1)
print(res)  # [11, 12, 21, 22, 32, 53, 64, 76] 默认升序

常见内置函数

1.abs() 绝对值
返回数字绝对值或复数的模
abs(-2)  # 2
abs(5j + 4)  # 6.4031242374328485
2.all() 接受一个迭代器,如果迭代器(元组或列表)的所有元素都为真,那么返回True,否则返回False,元素除了是0、空、None、False外都算 True。注意:空元组、空列表返回值为True,这里要特别注意。
print(all([0, 1, 2, 3]))  # False
print(all([1, 2, 3, True]))  # True
3.any()接受一个迭代器,如果迭代器里有一个元素为真,那么返回True,否则返回False,元素除了是 0、空、None、False 外都算 True。
print(any([0, None, '', 1]))  # True
print(any([0, None, '']))  # False
4.bin()
将十进制转换为二进制
oct()
将给的参数转换成八进制
hex()
用于将10进制整数转换成16进制
int()
int(x, base =10)
x -- 字符串或数字。
base -- 进制数,默认十进制。
5.bytes()
将一个字符串转换成字节类型
s1 = '今天周五'
print(s1.encode('utf8'))  # b'\xe4\xbb\x8a\xe5\xa4\xa9\xe5\x91\xa8\xe4\xba\x94'
print(bytes(s1, 'utf8'))  # b'\xe4\xbb\x8a\xe5\xa4\xa9\xe5\x91\xa8\xe4\xba\x94'
6.callable()
用于检查一个对象是否是可调用的
name = 'jason'
def index():
    print('from index')
print(callable(name))  # False
print(callable(index))  # True
7.chr()ord()
基于ASCII码表做数字与字母的转换
print(chr(65))  # A
print(ord('A'))  # 65
8.dir()
可以查看括号内对象的属性和方法
9.divmod()
元组 第一个数据为整除数 第二个是余数
res = divmod(100, 2)
print(res)  # (50, 0)
res = divmod(100, 3)
print(res) # (33, 1)
"""
总数据     每页展示的数据     总页码
100         10              10
99          10              10
101         10              11
"""
print(divmod(99, 10))  # (9, 9)
page_num, more = divmod(9999, 20)
if more:
    page_num += 1
print('总页码为:', page_num)  # 总页码为: 500
10.enumerate()
用于将一个可遍历的数据对象(如列表、元组或字符串)组合为一个索引序列,同时列出数据和数据下标,一般结合for循环使用
语法:enumerate(sequence, [start=0])
参数:
sequence -- 一个序列、迭代器或其他支持迭代对象。
start -- 下标起始位置。
11.eval() exec() 能够识别字符串中的python代码并执行
s1 = 'print("哈哈哈")'
eval(s1)
exec(s1)
s2 = 'for i in range(100):print(i)'
eval(s2)  # 报错 只能识别简单的python代码 具有逻辑性的都不行
exec(s2)  # 可以识别具有一定逻辑性的python代码
12.hash()  哈希加密
print(hash('jason'))  # -5110295089852496299
13.id() 
返回对象的内存地址
isinstance()
判断一个对象是否是一个已知的类型
15.pow()
幂指数(次方)
print(pow(2, 2))  # 4
print(pow(2, 3))  # 8
print(pow(2, 4))  # 16
16.round() 四舍五入
print(round(98.5))  # 98
print(round(98.6))  # 99
17.sum() 求和
print(sum([11, 22, 33, 44, 55, 66]))  # 231
18.staticmethod()
返回函数的静态方法,一般通过装饰器的形式使用,方便将外部函数集成到类体中
19.repr()
将对象转化为供解释器读取的形式,返回一个对象的 string 格式

可迭代对象

1.可迭代对象
	对象内置有__iter__方法的都称为可迭代对象
	"""
	1.内置方法  通过点的方式能够调用的方法
	2.__iter__  双下iter方法
	"""
2.可迭代对象的范围
	不是可迭代对象
    	int float bool 函数对象
	是可迭代对象
    	str list dict tuple set 文件对象
3.可迭代的含义
	"""
	迭代:更新换代(每次更新都必须依赖上一次的结果)
		eg:手机app更新
	"""
	可迭代在python中可以理解为是否支持for循环

迭代器对象

1.迭代器对象
	是由可迭代对象调用__iter__方法产生的
	迭代器对象判断的本质是看是否内置有__iter__和__next__
2.迭代器对象的作用
	提供了一种不依赖于索引取值的方式
	正因为有迭代器的存在 字典 集合才能够被for循环
3.迭代器对象实操
s1 = 'hello'  # 可迭代对象
res = s1.__iter__()  # 迭代器对象
print(res.__next__())  # 迭代取值 for循环的本质
一旦__next__取不到值 会直接报错
4.注意事项
	可迭代对象调用__iter__会成为迭代器对象 迭代器对象如果还调用__iter__不会有任何变化 还是迭代器对象本身

for循环的本质

for 变量名 in 可迭代对象:
    循环体代码
"""
1.先将in后面的数据调用__iter__转变成迭代器对象
2.依次让迭代器对象调用__next__取值
3.一旦__next__取不到值报错 for循环会自动捕获并处理
"""

异常捕获/处理

1.异常
	异常就是代码运行报错 行业俗语叫bug
	代码运行中一旦遇到异常会直接结束整个程序的运行 我们在编写代码的过程中要尽可能避免
2.异常分类
	语法错误
		不允许出现 一旦出现立即改正
	逻辑错误
    	允许出现的 因为它一眼发现不了 代码运行之后才可能出现
3.异常结构
	错误位置
	错误类型
	错误详情

标签:总结,index,函数,res,第三周,time,print,def
From: https://www.cnblogs.com/qian-yf/p/16796739.html

相关文章