Python知识十一(递归函数 算法(二分法) 三元表达式 列表生成式 字典生成式 匿名函数 常见内置方法 迭代器)

昨日内容回顾

  • 简易版本装饰器

    """装饰器不是一门新的技术 而是由名称空间 函数对象 闭包函数组合而来"""
    1.给一个函数添加一个统计时间的功能
    	def index():
            pass
    2.在调用该函数的前后添加了一些额外的代码
    	start_time
        index()
        end_time
    3.统计时间的代码在程序的很多地方都需要反复执行  >>>  封装成函数
    	def get_time():
            start_time
            index()
            end_time
    4.封装成函数之后为了解决兼容性问题(能够统计不同函数的执行时间)
    	def get_time(func):
            start_time
            func()
            end_time
    5.上述封装过程出现了违背装饰器原则问题
    	def outer(func):
            # func = index
            def get_time():
                start_time
                func()
                end_time
            return get_time
        index = outer(index)
        index()
    
  • 装饰器解决参数问题

    def outer(func):
            # func = index
            def get_time(*args,**kwargs):
                start_time
                func(*args,**kwargs)
                end_time
            return get_time
    index = outer(index)
    index()
    
  • 装饰器解决返回值问题

    def outer(func):
        def get_time(*args,**kwargs):
            start_time
            res = func(*args,**kwargs)
            end_time
            return res
        return get_time
    index = outer(index)
    res = index()
    
  • 认证装饰器(练手)

    """每个人都必须能够独立完成(每个函数执行都校验  全局校验)"""
    is_login = {'is_login':False}
    
  • 装饰器通用模板

    def outer(func):
        def inner(*args,**kwargs):
            # 执行被装饰函数(对象)之前可以执行的其他操作
            res = func(*args,**kwargs)
            # 执行被装饰函数(对象)之后可以执行的其他操作
            return res
        return inner
    
  • 装饰器语法糖

    @outer
    def index():
        pass
    # 1.语法糖必须紧挨着被装饰器对象
    # 2.语法糖会自动将紧挨着的对象当做参数加括号传入函数自动调用
    	index = outer(index)
    # 3.如果上方没有其他语法糖则直接使用与被装饰对象相同的变量名接收装饰器返回值
    
  • 语法糖使用(双层、三层)

    @outer1  # index = outer1(outer2函数的返回值(函数名))
    @outer2  # outer2函数的返回值(函数名) = outer2(outer3函数的返回值(函数名))
    @outer3  # outer3函数的返回值(函数名) = outer3(真正的index)
    def index():
        pass
    # 语法糖由下往上自动执行
    
  • 装饰器修复技术

    help()  # 可以查看函数的基本信息(函数名 函数注释)
    
    '''如何做到无法轻易看出是否被装饰'''
    from functools import wraps  # 固定句式
    def outer(func):
        @wraps(func)  # 固定句式
        def inner(*args,**kwargs):
            # 执行被装饰函数(对象)之前可以执行的其他操作
            res = func(*args,**kwargs)
            # 执行被装饰函数(对象)之后可以执行的其他操作
            return res
        return inner
    
  • 有参装饰器

    如果装饰器内部还需要额外的参数
    from functools import wraps  # 固定句式
    def outers(others):
        def outer(func):
            @wraps(func)  # 固定句式
            def inner(*args,**kwargs):
                # 执行被装饰函数(对象)之前可以执行的其他操作
                others
                res = func(*args,**kwargs)
                # 执行被装饰函数(对象)之后可以执行的其他操作
                return res
            return inner
        return outer
    @outers(123)  # 先执行outers函数 之后再执行语法糖功能
    

今日内容概要

  • 递归函数
  • 算法(二分法)
  • 三元表达式
  • 列表生成式 字典生成式
  • 匿名函数
  • 常见内置方法
  • 迭代器

今日内容详细

递归函数 (自我嵌套)

"""
递归:函数在运行过程中 直接或者间接的调用了自身
"""

# 官网表示:python默认的最大递归深度为1000次
# import sys
# print(sys.getrecursionlimit())
# print(sys.setrecursionlimit(2000))
count = 1
def index():
    global count
    count += 1
    print(count)
    print('from index')
    index()
index()

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


"""
递归
    1.递推
        一层层往下推导答案(每次递归之后复制度相较于上一次一定要有所下降)
    2.回溯
        依据最后的结论往后推导出最初需要的答案
    递归一定要有结束条件!!!
"""


# 伪代码:可能无法运行 但是可以表述逻辑
# age(5) = age(4) + 2
# age(4) = age(3) + 2
# age(3) = age(2) + 2
# age(2) = age(1) + 2
# age(1) = 18

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


l = [1,[2,[3,[4,[5,[6,[7,[8,[9,[10,[11,[12,[13,[14,]]]]]]]]]]]]]]
# 打印出列表中每一个元素(列表除外)
# 1.循环该列表 获取列表内每一个元素
# 2.判断该元素是否是数字 如果是数字 则直接打印
# 3.如果是列表 则循环该列表 获取列表内每一个元素
# 4.判断该元素是否是数字 如果是数字 则直接打印
# 5.如果是列表 则循环该列表 获取列表内每一个元素
# 6.判断该元素是否是数字 如果是数字 则直接打印
# 7.如果是列表 则循环该列表 获取列表内每一个元素
def get_num(l):
    for i in l:
        if type(i) is int:
            print(i)
        else:
            # 也是for循环 然后判断
            get_num(i)
get_num(l)

# for i in []:
#     print(i,'懵逼了!')

算法之二分法 (递归函数自我嵌套)

# 什么是算法?
	解决问题的高效方法
   
# 二分法(入门级别:还有一定距离)
	l = [11, 23, 43, 57, 68, 76, 81, 99, 123, 321, 432, 567, 666, 712, 899, 999, 1111]
# 第一种方式  直接for循环从左往右依次查找

# 第二种方式  二分法
"""
二分法能够使用的场景  数据集必须有序
"""
def two_part(want_number,l):  # target_num=321  l=l
        if len(l) == 0:
        print('i cant do it')
        return
    # 先获取中间位置索引值
    middle_len = len(l) // 2
    middle_number = l[middle_len]  # 8
    # 判断中间索引对应的值比目标值大还是小
    # 说明要找的元素只可能出现在列表的左侧
        if want_number > middle_number:
        right_l = l[middle_len + 1:]
        print(right_l)
        two_part(want_number,right_l)
        # 说明要找的元素只可能出现在列表的右侧
        elif want_number < middle_number:
        left_l = l[:middle_len]
        print(left_l)
        two_part(want_number,left_l)
        
        else:
        print('get it!!',want_number)

two_part(444,l)
# my_partner(444, l)  找不到 需要添加结束条件
# my_partner(11, l)  # 要查找的元素在开头  那么还没有依次查找的效率高

三元表达式

# def my_max(a, b):
#     if a > b:
#         return a
#     else:
#         return b
"""
当功能需求仅仅是二选一的情况下 那么推荐使用三元表达式
"""
def number_max(a,b):
    print(a if a > b else b)

number_max(1,2)
"""
条件成立采用if前面的值 if 条件 else 条件不成立采用else后面的值
三元表达式尽量不要嵌套使用
"""
res = '干饭' if 10 > 2 else '不干饭'
print(res)
res = '干饭' if 10 > 2 else ('不管饭' if 2 >5 else '写的啥!')
print(res)


get_answer = input("yes/no?\n")
print('去吃日料' if get_answer == 'yes' else '开房')

列表生成式

name_list = ['jason', 'kevin', 'tony', 'jerry']
# 给列表中所有的人名加上_DSB后缀
'''传统做法'''
# 1.定义一个空列表
new_list = []
# 2.for循环老列表
for name in name_list:
# 3.生成新的名字
new_name = '%s_DSB'%name
# 4.添加到新的列表中
new_list.append(new_name)
print(new_list)
\\\\\\\\\\\\\\
'''列表生成式'''
name_list = ['jason', 'kevin', 'tony', 'jerry']
res = ['%s_DSB' % name for name in name_list]
print(['%s_DSB' % name for name in name_list])


'''传统做法'''
# 1.定义一个空列表
# new_list = []
# # 2.for循环老列表
# for name in name_list:
#     # 3.生成新的名字
#     if name == 'jason':
#         continue
#     else:
#         new_name = '%s_DSB'%name
#         # 4.添加到新的列表中
#         new_list.append(new_name)
# print(new_list)

\\\\\\\\\\\\\\
'''列表生成式'''
res = ['%s_DSB' % name for name in name_list if name != 'jason']
print(res)

enumerate(L,start=)枚举字典生成式

'''传统做法'''
l1 = ['name', 'age', 'hobby']
l2 = ['jason', 18, 'read']
new_dict = {}
'''传统做法'''方法一:
for i in range(len(l1)):
    new_dict[l1[i]] = l2[i]
print(new_dict)
'''传统做法'''方法二:
for i in l1:
    dic[l1[count]] = l2[count]
    count += 1
print(dic)


# 枚举enumerate(枚举) 
'''
enumerate(l1)
    针对该方法使用for循环取值 每次会产生两个结果
        第一个是从0开始的数字
        第二个是被循环对象里面的元素
    还可以通过start参数控制起始位置
'''
'''''for i, j in enumerate(l1, start=1):
    print(i, j)


name_list = ['jason', 'kevin', 'tony', 'jerry']
res = {i: j for i, j in enumerate(name_list) if j != 'jason'}
print(res)

res1 = {i for i,j in enumerate(name_list)}
print(res1,type(res1))


# 迭代器
res2 = (i for i,j in enumerate(name_list))
print(res2)'''

匿名函数

# 匿名函数:没有名字的函数
"""
语法格式
    lambda 形参:返回值
"""
print(lambda x:x**2)
def index():
    pass
print(index)
print((lambda x: x ** 2)(2))
res = lambda x: x ** 2
print(res(2))

'''匿名函数一般不会单独使用 都是配合其他函数一起使用'''
map()  映射
l = [1, 2, 3, 4, 5, 6, 7, 8, 9]
def index(n):
    return n ** 2
print(list(map(lambda x:x**2, l)))

作业

整理今日内容及博客
1.装饰器继续自己专研
2.认证装饰器(全局)
预习明日内容
	https://blog.sholdboyedu.com/?p=3406
posted @ 2021-11-18 21:52  弑悟  阅读(6)  评论(0)    收藏  举报