目录
一、算法简介之二分法(需要写的出来)
简介
关于算法我们只需要稍微了解一下就可以了,对于算法,刚入行的小白基本上是接触不到相关工作的,除了顶尖高效的相关专业可以直接找到工作,通常情况下需要我们在进入一些大公司工作一段时间后,被调到算法部门,才是正常的工作流程。对于算法这个东西,小公司不会成立相关部门研究算法,只有大公司才会成立部门研究算法,因为算法产出低,但是算法从业者的工资又相对偏高。小公司中的算法部门大多数情况都是拿别人的算法来改改用用的。
什么是算法
算法的范围很大,只要是解决问题的思路都算算法。但是不是所有的算法都是高效的,也有很多不合格的算法,可这并不影响算法的流行。因为算法的应用范围确实很广,几乎涵盖了我们生活中的方方面面:推荐算法(抖音视频推送 淘宝商品推送)、成像算法(AI相关)
常见算法的原理以及伪代码:
二分法、冒泡、快拍、插入、堆排、桶排、数据结构(链表 约瑟夫问题 如何链表是否成环)
二分法
二分法算是算法中最简单的算法,有很大缺陷,但是面试的时候喜欢拿来考一考。
二分法有以下限制条件:
1、进行运算的数据值需要是有序的。
2、运算的时候如果需要取得的数据值是在两头的,反而会更加耗时
# 查找列表中某个数据值
# 方式1:for循环 次数较多
# 方式2:二分法 不断的对数据集做二分切割
correct = 754
# 假设我们要找到啊754这个值
# 获取中间的索引,这里通过整除来弄
def find(l1):
# 如果列表中没有数据值就说明查找失败了
if len(l1) == 0:
return '没有找到'
middle = len(l1) // 2
if l1[middle] > correct:
# 如果中间这个数的值大于要找的这个值就取列表左边的列表继续查找
new_list = l1[:middle]
print(new_list)
return find(new_list)
elif l1[middle] < correct:
# 如果中间这个数的值小于要找的这个值就取列表右边的列表继续查找
new_list = l1[middle:]
print(new_list)
return find(new_list)
else:
# 除了大于和小于两种情况就是找到了那个值
return correct
print(find(l1))
二、三元表达式
什么是三元表本质?
1、是对简单的代码进行缩写,简单的来说就是偷懒的写法减少代码行数
2、三元表达式只适合较为简洁的条件判定,较为复杂的判定建议不要用这种方式写代码,因为比较让他人难以理解。
3、三元表达式不建议嵌套使用,因为三元表达式是为了简化代码,嵌套后反而看着更复杂了。
三元表达式语法结构
if条件判定为真时的结果+if 判定条件 else+if条件判定为假时的结果
如果if后面的条件成立,则使用if前面真的时候值
如果if后面的条件不成立,则使用else后面假的值
# 简化步骤1:代码简单并且只有一行 那么可以直接在冒号后面编写
name = 'jason'
# if name == 'jason':print('老师')
# else:print('学生')
# 三元表达式
res = '老师' if name == 'jason' else '学生'
print(res)
"""
数据值1 if 条件 else 数据值2
条件成立则使用数据值1 条件不成立则使用数据值2
当结果是二选一的情况下 使用三元表达式较为简便
并且不推荐多个三元表达式嵌套
"""
三、各种生成式
生成式总共有三种:列表生成式、字典生成式、集合生成式。元组类型没有生成式,元组类型叫生成器,会生成一个类似工程的东西,不会直接生成列表。
生成式的作用:用于对数据类型中的所有数据值进行进行相同操作
表现形式:
new_list = [name + "_NB" for name in name_list]
左边是变量名绑定修改后的结果,右边最外层的是最后生成数据的类型,通常来说我们都是用的什么生成器就在外层使用什么类型对应的外层符号。内层for循环左边的代码是规定进行的操作,for循环的作用就是一个个取值进行修改,因为外层套着框,所以修改后的值就依次保存在列表中了,如果是字典和集合的话因为本身的无序性,输出结果的时候可能会没有顺序。
列表生成式
# name_list = ['jason', 'kevin', 'oscar', 'tony', '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)
# new_list = ['大佬' if name == 'jason' else '小赤佬' for name in name_list if name != 'jack']
# print(new_list)
# 集合生成式
# res = {i for i in 'hello'}
# print(res)
# 元组生成式>>>:没有元组生成式 下列的结果是生成器(后面讲)
# res = (i+'SB' for i in 'hello')
# print(res)
# for i in res:
# print(i)
字典生成式
# 字典生成式
# s1 = 'hello world'
# for i,j in enumerate(s1,start=100):
# print(i,j)
# d1 = {i: j for i, j in enumerate('hello')}
# print(d1)
注:这里的i和j相当于进行了解压赋值操作,如果这里只有一个变量名,就等于绑定了一对键值对,这时候输出的值就键值对,两个变量的时候就是分别输出键和值。
集合生成式
# 集合生成式
# res = {i for i in 'hello'}
# print(res)
没什么特点,就是输出结果的时候是无序的
元组生成器(稍微介绍一下区别)
形式跟生成式差不多但是功能不一样
# 元组生成式>>>:没有元组生成式 下列的结果是生成器(后面讲)
# res = (i+'SB' for i in 'hello')
# print(res)
# for i in res:
# print(i)
生成的结果如果跟生成式一样输出的话,只能看到函数名称,如果使用for循环打印生成的结果的话就可以看到生成的一个个值
四、匿名函数
匿名函数就是用于在特定的情况下包装一些简单操作,这样就不需要特意定义函数了。
特点:没有函数名,直接执行功能代码
语法结构:
变量名 = lambda 参数 :返回值
这里的变量名用于获取函数名,当默认情况下所有的lambda函数的返回名称都是lambda只是功能不同
lambda a,b:a+b
匿名函数一般不单独使用,需要配合其他函数一起用,我们可以在接下来的内置函数中体现出来。
五、常见内置函数
1、map()——映射
map函数的功能就是映射,我们可以用匿名函数来举个例子:
l1 = [1, 2, 3, 4, 5]
# 假设我们要所有的l1中的数据值+1
a = map(lambda i:i+1,l1)
print(list(a))
如果我们直接print(a),我们得到结果时map函数的相关代码,但是当我们用list方法把a转换成列表之后打印就可以看到转换后的结果
2、max()和min()
max()和min()的作用就是取一组数据值中最大和最小的值,在字典中需要我们手动标出值,否则的话就会根据ascii码排字母大小(A-Z——65-90,a-z——97-122)来获得返回值。下面我们用max来举例:
l1 = [11, 22, 33, 44]
res = max(l1)
# 这里就不需要别的操作就可以直接获得最大值
d1 = {
'zj': 100,
'jason': 8888,
'berk': 99999999,
'oscar': 1
}
def func(a):
return d1.get(a)
res = max(d1, key=lambda k: d1.get(k))
# 这里的第一个参数是设置要查找的数据组,然后key的作用是对每个数据组中的元素先进行key绑定的函数进行操作在进行比较,但是最后的返回结果还是用函数操作前的对象。
# 使用max方法的时候也可以用匿名函数,如果感觉自己理解不了就可以先定义函数后调用
# res = max(d1, key=func)
print(res)
3、reduce()
这里的reduce已经不能算内置函数了,他由于使用频率少已经变成了一个模块,作用是统计。
使用前需要先引入模块
from functools import reduce
l1 = [11, 22, 33, 44, 55, 66, 77, 88]
res = reduce(lambda a, b: a * b, l1)
print(res)
这里的括号内参数功能跟max相似,第一个位置是放函数,用于定义统计的方式,第二个位置放列表之类的数据值,这里我们用了匿名函数定义统计方式,如果我们匿名函数的功能是a+b,得到的就是l1中所有值相加的结果,如果匿名函数的功能时a*b,得到的结果就是所有的列表中的值相乘。这里我们不需要想的很细致,当python解释器很智能就可以,会根据对应的条件计算。
六、作业
附加题
有下列用户数据
user_data = {
'1': {'name': 'jason', 'pwd': '123', 'access': ['1', '2', '3']},
'2': {'name': 'kevin', 'pwd': '321', 'access': ['1', '2']},
'3': {'name': 'oscar', 'pwd': '222', 'access': ['1']}
}
并有三个函数
def func1():
pass
def func2():
pass
def func3():
pass
要求:调用上述三个函数的时候需要从user_data中校验用户身份是否正确
并获取当前登录用户拥有的可执行函数功能编号即键access对应的功能编号列表
func1是1、func2是2、func3是3
并且一旦用户登录成功之后后续函数的调用不再校验用户身份
请思考如何获取函数功能编号 如何校验用户身份 如何校验权限
ps:装饰器知识 附赠:实现上述主体功能即可 其他扩展优化功能可暂且不写
'''
1.先编写校验用户身份的装饰器
2.然后再考虑如何保存用户登录状态
3.再完善各种需求
'''
user_data = {
'1': {'name': 'jason', 'pwd': '123', 'access': ['1', '2', '3']},
'2': {'name': 'kevin', 'pwd': '321', 'access': ['1', '2']},
'3': {'name': 'oscar', 'pwd': '222', 'access': ['1']}
}
由于题目里的东西太low了,我就改了一下之前的代码,基本情况就是用户登陆后根据不同的账号有不同的权限(这里设置成非管理员不能注册新用户),有权限的可以干下面被装饰函数中的功能。
# 执行程序之前选择登陆方式
ch = input('请选择登陆方式:\n1、直接登陆(管理员登陆)\n2、字典用户登陆\n请选择:')
# 定义一个变量判断是否登陆,另一个变量记录登陆的用户名
is_log_in = False
log_in_name = ''
function_u = []
# 装饰器
def outer(add_n):
def middle(func):
def inner(*args, **kwargs):
# 使用函数前 先进行判断,如果已经登陆过了就直接执行对应功能的代码,没有登陆就先登陆
global is_log_in
global log_in_name
global function_u
res00 = False
# 声明一下这里后面修改的都是全局中的变量
# 如果已经登陆过了就直接执行功能
if is_log_in:
res = func(*args, **kwargs)
return res
else:
# 如果没登陆就需要先登陆
print('进行操作前需先验证身份')
login_uname = input('请输入账号').strip()
login_upwd = input('请输入密码').strip()
# 输入信息进行登陆
if add_n == '1':
# 直接登陆(搞个固定信息,当成管理员账号)
if login_uname == 'zzh' and login_upwd == '666':
res00 = True
is_log_in = True
function_u = dictionary_log_dict['access13']
else:
res00 = '用户名或密码错误'
# elif add_n == '2':
# # 文本登陆(搞个txt存信息)
# with open(r'D:\pythonproject\c.txt', 'r', encoding='utf8') as f0:
# r_inf = f0.readlines()
# # 打开文件获取其中用户信息
# is_log = False
# # 定义变量判断是否登陆成功
# for i in r_inf:
# r_n, r_p = i.split('|')
# if r_n == login_uname and r_p + '\n' == login_upwd:
# # 登陆成功就修改登陆状态
# is_log = True
# is_log_in = True
# if is_log:
# res00 = True
# else:
# res00 = '用户名或密码错误'
elif add_n == '3':
# 字典登陆(搞个字典存信息)
# 这里直接调用函数判断
res00 = login(login_uname, login_upwd)
if res00:
# 登陆成功后更改全局变量中的状态和登陆对象(在login函数中改的is_log_in)
log_in_name = login_uname
if operation in function_u:
res = func(*args, **kwargs)
# 执行被装饰对象之后可以做的额外操作
return res
else:
return '没有权限或账号信息错误'
# 登陆成功返回布尔值,登陆失败返回提示
return inner
return middle
# 定义一个函数用于注册
@outer(ch)
def register(username, password):
is_reuse = False
# 定义变量判断是否登陆成功
for i in dictionary_log_dict:
# 遍历数据值拆开对比
inf_t_n, inf_t_p = dictionary_log_dict[i].split('|')
if inf_t_n == username:
# 名称重复就停止
is_reuse = True
return '重复的用户名'
if is_reuse == False:
# 名称没有重复就开始往字典中添加信息
ch = str(len(dictionary_log_dict) + 1)
dictionary_log_dict['user_infor' + ch] = '|'.join([username, password])
# 新用户默认金额为0
dictionary_infor_dict[username] = 0
return '注册成功'
# 定义一个函数用于判断用户输入的信息是否正确
def login(username, password):
answer = False
for i in dictionary_log_dict:
inf_t_n, inf_t_p = dictionary_log_dict[i].split('|')
if inf_t_n == username and inf_t_p == password:
answer = True
is_log_in = True
log_in_name = username
n_useless,n_n = i.split('infor')
function_u = dictionary_log_dict['access'+n_n]
if answer:
return answer
else:
return '用户名或密码错误'
# 定义一个函数用于转账
@outer(ch)
def transfer(tran_n, tran_m):
# 定义转账的对象、金额
is_t_t = False
for i in dictionary_log_dict:
inf_t_n, inf_t_p = dictionary_log_dict[i].split('|')
if inf_t_n == tran_n:
# 转账对象在数据库中时进行转账
dictionary_infor_dict[tran_n] += tran_m
dictionary_infor_dict[log_in_name] -= tran_m
# re = dictionary_infor_dict[log_in_name]
print('剩余金额:' + str(dictionary_infor_dict[log_in_name]))
is_t_t = True
return '转账成功'
if is_t_t == False:
print(inf_t_n)
return '转账信息输入错误'
# 定义一个函数用于提现
@outer(ch)
def withdraw(m_num):
# 提现之后金额减少,之间做减法
dictionary_infor_dict[log_in_name] = dictionary_infor_dict[log_in_name] - m_num
print('剩余金额:' + str(dictionary_infor_dict[log_in_name]))
return '提现成功'
# 定义一个数据库存储数据值
dictionary_log_dict = {'user_infor1': '虹桥炮王|123', 'access1': ['1', '3', '4'],
'user_infor2': '猪猪男孩小康康|123', 'access2': ['1', '3', '4'],
'user_infor3': '赵世漫|123', 'access3': ['1', '3', '4'],
'user_infor4': '李帆|123', 'access4': ['1', '3', '4'],
'user_infor5': '段宇航|123', 'access5': ['1', '3', '4'],
'user_infor6': '猪猪男孩张红|123', 'access6': ['1', '3', '4'],
'user_infor7': '吴强|123', 'access7': ['1', '3', '4'],
'user_infor8': '陈傲|123', 'access8': ['1', '3', '4'],
'user_infor9': '郭贺阳|123', 'access9': ['1', '3', '4'],
'user_infor10': '李明轩|123', 'access10': ['1', '3', '4'],
'user_infor11': '宋晨晓|123', 'access11': ['1', '3', '4'],
'user_infor12': '刘少伟|123', 'access12': ['1', '3', '4'],
'user_infor13': 'zzh|666', 'access13': ['1', '2', '3', '4']}
# 定义一个字典存储用户余额
dictionary_infor_dict = {'虹桥炮王': 999,
'猪猪男孩小康康': 999,
'赵世漫': 999,
'李帆': 999,
'段宇航': 999,
'猪猪男孩张红': 999,
'吴强': 999,
'陈傲': 999,
'郭贺阳': 999,
'李明轩': 999,
'宋晨晓': 999,
'刘少伟': 999,
'zzh': 99999
}
while True:
operation = input('功能简介:\n1、登陆\n2、注册\n3、转账\n4、提现\n5、退出\n请输入需要执行的指令:')
if operation == '1':
# 选择了登陆
login_uname = input('请输入账号').strip()
login_upwd = input('请输入密码').strip()
# 调用函数进行判断
ans1 = login(login_uname, login_upwd)
if ans1:
is_log_in = True
print('登陆成功')
elif operation == '2':
# 选择了注册
sign_uname = input('请输入需要注册的账号').strip()
sign_upwd = input('请输入需要注册的账号的密码').strip()
# 调用函数进行判断
ans2 = register(sign_uname, sign_upwd)
print(ans2)
elif operation == '3':
# 选择了转账
t_n = input('请输入转账对象名称:').strip()
t_m = int(input('请输入转账金额:').strip())
# 调用函数进行转账功能
tran = transfer(t_n, t_m)
print(tran)
elif operation == '4':
# 选择了提现
number_out = int(input('请输入需要提现的金额:').strip())
# 调用函数进行提现功能
with_h = withdraw(number_out)
print(with_h)
elif operation == '5':
# 选择了退出
break
else:
print('请输入正确的指令')