函数进阶:算法简介及二分法、三元表达式、各种生成式、匿名函数、常见内置函数

一、算法简介之二分法(需要写的出来)

简介

关于算法我们只需要稍微了解一下就可以了,对于算法,刚入行的小白基本上是接触不到相关工作的,除了顶尖高效的相关专业可以直接找到工作,通常情况下需要我们在进入一些大公司工作一段时间后,被调到算法部门,才是正常的工作流程。对于算法这个东西,小公司不会成立相关部门研究算法,只有大公司才会成立部门研究算法,因为算法产出低,但是算法从业者的工资又相对偏高。小公司中的算法部门大多数情况都是拿别人的算法来改改用用的。

什么是算法

算法的范围很大,只要是解决问题的思路都算算法。但是不是所有的算法都是高效的,也有很多不合格的算法,可这并不影响算法的流行。因为算法的应用范围确实很广,几乎涵盖了我们生活中的方方面面:推荐算法(抖音视频推送 淘宝商品推送)、成像算法(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相当于进行了解压赋值操作,如果这里只有一个变量名,就等于绑定了一对键值对,这时候输出的值就键值对,两个变量的时候就是分别输出键和值。
enumerate方法是给输出的值输出一个序号,可以自己设置起点的值。

集合生成式

# 集合生成式 # 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()

python2中reduce是内置方法可以直接调用,但是在python3中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: 装饰器知识
# 附赠: 实现上述主体功能即可
# 其他扩展优化功能可暂且不写

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']}
}
'''
1.先写模板
2.先获取用户的编号,再写用户校验
3.记录用户登录状态
4.再考虑用户权限问题
'''
is_login = {
    'login_status':False,  # 记录用户是否登录
    'user_access':None    # 记录登录用户的权限
}
def login_auth(func_id):
    def outer(func_name): # 形参是用来接收被装饰的函数的
        def inner(*args, **kwargs):  # 被装饰的函数的参数
            # 6.先校验用户是否登录
            if is_login.get('login_status'):# 这段代码是如果用户已经登录,就不用执行下面的步骤了,如果没有需要登录
            # 8.也需要校验功能编号是否在当前登录的用户权限中
                if func_id not in is_login.get('user_access'):
                    print(f'您没有功能编号为{func_id}的函数执行权限')
                    return
                res = func_name(*args, **kwargs)
                return res
            # 1.先获取用户的编号
            user_id = input('请输入您的编号>>>:').strip()
            # 2.校验用户编号是否存在
            if user_id not in user_data:
                  print('用户编号不存在 无法完成身份校验')
                  return
            # 3.获取用户用户名和密码
            username = input('请输入您的用户名>>>:').strip()
            password = input('请输入您的密码>>>:').strip()
            # 4.获取用户编号对应的真实数据进行比对
            user_dict = user_data.get(user_id)
            if user_dict.get('name') == username and user_dict.get('pwd') == password:
            # 5.登录成功之后修改字典中登录状态
                is_login['login_status'] = True
            # 6.记录当前登录用户的权限编号 用户只要登录了就能拿到当前用户的编号
                is_login['user_access'] = user_dict.get('access')
            # 7.校验当前函数编号是否在当前用户权限列表内 如果在就能执行,如果不在就不能执行
                if func_id in user_dict.get('access'):  #函数体代码需要一个东西,只能传参
                    res = func_name(*args, **kwargs) # func_name是被装饰的函数的函数名
                    return res   # 这时我们返回了一个编号,然后我们再判断是否有权限
                else:
                    print(f'您没有功能编号为{func_id}的函数执行权限')
            else:
                print('用户名或密码错误')
        return inner
    return outer


@login_auth('1')          # outer相当于跑res = func_name(*args, **kwargs)和return res
def func1():
    print('from func1')
@login_auth('2')
def func2():
    print('from func2')
@login_auth('3')
def func3():
    print('from func3')
func1()
func2()
func3()
posted @ 2022-10-13 19:50  wwwxxx123  阅读(68)  评论(0编辑  收藏  举报