内置函数 lambda sorted filter map 递归

一 lambda 匿名函数

  为了解决一些简单的需求而设计的一句话函数

# 计算 n 的 n次方

def func(n):
    return n**n
print(func(10))



f = lambda n:n**n
print(f(10))

lambda 表示的是 匿名函数,不需要用 def 声明,一句话就可以声明出一个函数 

语法:

  l函数名 = lambda 参数:返回值

注意:

  1.返回值可以是一个,也可以是多个,多个 的时候用  逗号  隔开   在 元祖 () 里边

  2.lambda 不管多复杂 只能写 一行 , 执行完毕 返回数据

  3.lambda 和正常 函数一样 ,返回值 可以 是 任意 数据类型 

      匿名函数并不是说一定没有名字. 这里前面的变量就是一个函数名. 说他是匿名原因是我们通
过__name__查看的时候是没有名字的. 统一都叫lambda. 在调用的时候没有什么特别之处.像正常的函数调用即可

二  sorted     排序函数

语法:

  sorted(iterable,key = None,reverse=False)

      iterable :可迭代对象

      key = 排序规则(排序函数)   在  sorted 内部 会将 可迭代对象中的 每一个 元素传递给 这个函数的参数

         根据 函数运算的 结果进行 排序

      reverse; 是否是 倒序      True 倒序   False   正序

lst = [1,5,8,9,2,6,4,3,7]
lst1 = sorted(lst)
print(lst)    # [1, 5, 8, 9, 2, 6, 4, 3, 7] 原列表不变
print(lst1)   # [1, 2, 3, 4, 5, 6, 7, 8, 9] 返回的列表是经过排序的

dic = {1:"a",3:"b",2:"c"}
dic1 = sorted(dic)
print(dic)          #  {1: 'a', 3: 'b', 2: 'c'}
print(dic1)      #  [1, 2, 3] 如果是字典,返回经过排序的 key
# 和 函数 组合使用
lst = ["张曼玉","邱淑贞","朱茵","","上官寒冰"]
def func(s):
    return len(s)

print(sorted(lst,key=func))
# ['你', '朱茵', '张曼玉', '邱淑贞', '上官寒冰']


# 和 lambda 组合使用
lst = ["张曼玉","邱淑贞","朱茵","","上官寒冰"]

lst1 = (sorted(lst,key = lambda s:len(s)))
print(lst1)   #  ['你', '朱茵', '张曼玉', '邱淑贞', '上官寒冰']


lst = [{"id":1, "name":'alex', "age":18},
{"id":2, "name":'wusir', "age":16},
{"id":3, "name":'taibai', "age":17}]

# 按照年龄对学生进行排序

func = sorted(lst,key=lambda dic:dic["age"])
print(func)
 

三 filter()  筛选函数

语法:

  filter(function,iterable)

    function:用来筛选的函数,在 filter 中 会自动的吧 iterable  中的 元素传递个i function,然后根据 function返回

        的 True  或者  False 来判断是否保留 此项数据

    iterable : 可迭代对象

#筛选所有的 偶数
lst = [1,2,3,4,5,6,7,8,9]
l = filter(lambda x:x % 2 == 0,lst)
print(l)         # <filter object at 0x013E7690>
print(list(l))   #  [2, 4, 6, 8]


lst = [{"id":1, "name":'alex', "age":18},
        {"id":2, "name":'wusir', "age":16},
        {"id":3, "name":'taibai', "age":17}]

# 筛选年龄大于 16 的数据
lst1 = filter(lambda dic:dic["age"]>16,lst)
print(list(lst1))

# [{'id': 1, 'name': 'alex', 'age': 18}, {'id': 3, 'name': 'taibai', 'age': 17}]

四 map() 映射函数

  语法:

    map(function,iterable) 可以对 可迭代对象中的 每一个 元素 进行映射 ,分别取执行 function 

#  计算列表中 每个元素的 平方,返回新列表
# 1.和函数 组合 使用

def func(s):
    return s**2

mp = map(func ,[1,2,3,4])
print(mp)             ##   <map object at 0x013F7710>
print(list(mp))       ##   [1, 4, 9, 16]


# 2.和 lambda 组合 使用

print(list(map(lambda i:i**2,[1,2,3,4])))
# [1,4,9,16]


# 计算两个 列表中 相同 位置的数据的 和

lst = [1,2,3,4,5]
lst1 = [5,4,3,2,1]

print(list(map(lambda x,y:x+y,lst,lst1)))  #  [6, 6, 6, 6, 6]

五    reduce()  通过某个函数,累计按顺序计算列表中的值  可以 算 累加   累乘 等等吧

python2.x 中 直接  import reduce

python3.x  中    from functools import reduce

from functools import reduce
def func(x,y):
    return x + y

# reduce 的使用方法
# reduce(函数名,可迭代对象) # 这两个参数必须都要有,缺一个不行
ret = reduce(func,[3,4,5,6])
print(ret)


reduce 的作用是 先把列表中的 前两个元素取出计算一和值,然后临时保存
接下来用这个零时保存的值 和 列表中的下一个 再计算,以此类推 

# 注意 我们放进去的可迭代对象没有 更改
from functools import reduce    #  导入reduce 模块


#  和 lambda 组合 使用 

print(reduce(lambda x,y:x*y,[1,2,3,4]))   # 24

六 zip()  拉链函数   

zip(*iterables) 生成一个 迭代器(迭代器本质是 生成器),它聚合了 可迭代对象的 每个元素

返回 一个 由 元祖组成的 迭代器,其中 第 i 个元祖 包含 来自每个参数序列 或 可迭代对象的 第i个元素,

当最短的 可迭代对象被 输出时,该 迭代器完成

# 原理如下
def zip(*iterables):
    # zip("ABCD","xy") ---> Ax By
    sentinel = object()
    itetators = [iter(it) for it in iterables]
    while itetators:
        result = []
        for it in itetators:
            elem = next(it,sentinel)
            if elem is sentinel:
                return
            result.append(elem)
            yield tuple(result)

f = zip([1,2,3],[4,5,6,7])

print(f.__next__())     # (1,)
print(f.__next__())     # (1, 4)
print(f.__next__())    #  (2,)
print(f.__next__())    #  (2, 5)

x = [1,2,3,4]
y = ["张曼玉","邱淑贞","张敏"]
z = [11,22,33,44,55]

print(list(zip(x,y,z)))
# [(1, '张曼玉', 11), (2, '邱淑贞', 22), (3, '张敏', 33)]

print(list(zip(*zip(x,y,z))))
# [(1, 2, 3), ('张曼玉', '邱淑贞', '张敏'), (11, 22, 33)]
# * 的作用是把上面生成的 迭代器 又 再次 拉链式的 组合了该 迭代器中的 元素
lst = [1,2,3,4,5,6]
lst1 = ["anglobay","haha","hahag","张敏","邱淑贞"]
tu = ("**","***","****","******")

b = filter(lambda x:x[0] > 2 and len(x[2]) > 4,zip(lst,lst1,tu))
print(list(b))

# [(4, '张敏', '******')]

七  递归函数     在函数中调用函数本身,就是递归

递归是什么

在数学和计算机科学中,递归指由一种(或多种)简单的基本情况定义的一类对象或方法,

并规定其他所有情况都能被还原为其基本情况。

递归的三要素

  • 一个问题的解可以分解为几个子问题的解
  • 这个问题与分解之后的子问题,除了数据规模不同,求解思路完全一样
  • 一定存在终止递归的条件

关键点

  • 写出递推公式
  • 找到终止条件
  • 将递推公式转化为代码

递归代码要警惕堆栈溢出

函数调用会使用栈来保存临时变量,每调用一个函数,都会将临时变量封装为栈帧压入内存栈,等函数执行完成返回时,才出栈。系统栈或者虚拟机栈空间一般都不大,如果递归求解的数据规模很大,调用层次很深,一直压入栈,就会有堆栈溢出的风险。

如何避免堆栈溢出?

  • 在代码中限制递归调用的最大深度,当递归调用超过一定深度,比如1000之后,就不再继续往下递归了,直接返回报错。但是如果递归深度比较大,这种方法就不太适用。
  • 采取循环的方式来解决,将需要的数据在关键的调用点保存下来使用。简单的说,就是用自己的数据保存方法来代替系统递归调用产生的堆栈数据。 

递归代码要警惕重复计算

使用递归的时候,还会出现重复计算的问题。为避免重复计算,我们可以通过一个数据结构(比如散列表)来保存已经求解过的递归函数值 f(k),当递归调用到 f(k) 时,先看下是否已经求解过了,如果是,则直接从散列表中取值返回,不需要重复计算,这样就能避免重复计算了。

内容小结

  • 递归是一种非常高效、简洁的编程技巧。
  • 只要是满足“递归三要素”的问题,就可以通过递归代码来解决。
  • 编写递归代码的关键点在于:写出递推公式,找出终止条件,然后再翻译成递归代码。
  • 递归代码虽然简洁高效,但是也存在很多弊端,如:堆栈溢出、重复计算、函数调用耗时多、空间复杂度高等等,在使用递归时,一定要控制好这些副作用。
def func():
    print("我是func")
    func()
fucn()

# 在python 中,官方解释 递归最大深度1000,但是永远不会跑到1000
# 我实测 998

# 怎么测的 呢?? 其实很简单,就是利用累加 

def func(n):
    print(n)
    n += 1
    func(n)
func(1)

递归的应用:

  我们可以使用递归来遍历各种树形 结构,比如我们的文件夹系统

# 引入os 模块
import os

def func(filepath,n):
    files = os.listdir(filepath) # 获取到当前文件夹的所有文件
    for fi in files:             # 遍历文件夹中的 内容,这里获取到的是本层文件名
        fi_d = os.path.join(filepath,fi)  # 加入文件夹,获取到文件夹 + 文件
        if os.path.isdir(fi_d):     # 如果该路径下的是文件夹
            print("\t"*n,fi)      #  打印出文件名
            func(fi_d,n +1)      # 继续进行相同的 操作
        else:
            print("\t" * n, fi)   # 递归出口,最终在这里隐含着 return 
# 递归 遍历 d盘目录下 所有文件
func("d:/learn-py",0)

八  二分查找  

  每次查找能够排除掉一半 的数据,查找的效率 非常高,但是局限性比较大,必须是有序序列才可以用二分法

要求: 查找的序列 必须是 有序序列

#  二分查找 ----  非递归算法
lst = [1,2,3,4,5,6,7,8,9,11,22,33,44,55,66,77,88,99,100,101,111,222,333]

num = int(input("输入你要查找的数字:"))
left = 0
right = len(lst) - 1
count = 1
while left <= right:
    middle = (left + right) // 2
    if num > lst[middle]:
        left = middle + 1
    elif num < lst[middle]:
        right = middle - 1
    else:
        print(count)
        print(middle)
    count += 1
else:
    print("不存在")
# 普通 递归版本 二分法
# 利用 索引切片,切了列表,不符合的 切掉
# 当 列表 切完了之后,就可以判断了
# 很难计算 位置
lst = [1,2,3,4,5,6,7,8,9,11,22,33,44,55,66,77,88,99,100,101,111,222,333]

num = int(input("输入你要查找的数字:"))
def func(n,lst):
    left = 0
    right = len(lst) - 1
    if lst != []:
        middle = (left + right) // 2
        if num > lst[middle]:
            func(n,lst[middle + 1:])
        elif num < lst[middle]:
            func(n,lst[:middle])
        else:
            print("找到了")
            return None
    else:
        print("没找到")
        return None
print(func(num,lst))
# 判断 num 是不是在 列表中,可以返回 num 所在的 位置
# 用 递归,要找到设么是 可变的,什么是不可变的 \
# 列表不动
lst = [1,2,3,4,5,6,7,8,9,11,22,33,44,55,66,77,88,99,100,101,111,222,333]

num = int(input("输入你要查找的数:"))
def func(n,lst,left,right):
    if left <= right:
        middle = (left + right) // 2
        if n > lst[middle]:
            left = middle + 1
            return func(n,lst,left,right)
        elif n < lst[middle]:
            right = middle - 1
            return func(n,lst,left,right)
        else:
            print("找到了")
            return middle
    else:
        print("找不到")
        return -1
ret = func(num,lst,0,len(lst) - 1)
print(ret)
# 还有一种查找方法
# 堪称最快之 查找方法 ,此方法 不需要 列表是 有序的

lst = [1,2,55,66,88,3,44,6,5,7,8,111,222,333]
new_lst = []
for i in range(334):
    new_lst.append(i)
for el in lst:
    new_lst[el] = 1
num = int(input("输入你要查找的数字:"))
if new_lst[num] == 0:
    print("不存在")
else:
    print("存在")

猜你喜欢

转载自www.cnblogs.com/wenqi2121/p/10268644.html