匿名函数、函数递归与二分法、面向过程

知识汇总:

匿名函数:没有名字的函数
  lambda x: 表达式
特点: 在哪里使用在哪里定义并且只能使用一次

 

map
映射: 将可迭代对象中的数据按照表达式进行一一对应

 

filter
过滤: 将可迭代对象中的数据按照一定条件进行过滤得到一个新迭代器

 

reduce
合并: 将可迭代对象中的数据按照表达式进行合并

 

max
求最大值

min

求最小值

 

sorted
排序:默认是从小到大的自然顺序当然你可以结合匿名函数来自己指定排序的依据

 

sum
求和:要求可迭代对象中都是数字类型

 

递归
自己调用自己注意一定要设置出口(结束条件)否则栈溢出

 

二分法
对于一个有序的序列可以使用二分法提高查找效率
原理: 将整个序列分为两半然后判断要找的数据是在左边还是右边从而排除一半的数据

 

冒泡排序算法
[1, 5, 4, 3, 2]
从小到大排序
1, 4, 3, 2, 5
1, 3, 2, 4, 5
1, 2, 3, 4, 5
原理: 每次取出列表中两个元素进行比较
  如果左边的大于右边的交换位置(从小到大)
  如果左边的小于右边的交换位置(从大到小)

比较的次数是列表的长度 - 1
一趟比较完成后产生一个最大值,但是列表还是无序
第一趟 比较四次 长度5 - 1
第二趟 比较三次 长度4 - 1
第三趟 比较二次 长度3 - 1
第四趟 比较一次 长度2 - 1
需要两个循环:
  一个控制比较的趟数
  一个控制比较的次数

for i in range(len(li) - 1):
  for j in range(len(li) - 1 - i)
  # 每次取出两个值进行比较
    if li[j] > li[j + 1]:
      # 交换位置
      li[j], li[j + 1] = li[j + 1], li[j]

 

选择排序法:
每次从列表中找到一个最大值放到列表的右边或左边
[1, 3, 4, 5, 2]
从大到小最大下标为3和下标0交换

 

面向过程编程:
过程是什么?
完成一个事情经历的所有步骤就是过程
例如:帮我买瓶水的过程
1.给钱
2.下楼到商店
3.找矿泉水
4.付钱
5.拿着水上楼
6.交接


在代码中就是将复杂的任务简单化,流程化,就像设计一条流水线一样
缺点: 扩展性差
应用场景: 一个功能如果不需要进行扩展(不要求扩展性)写一个用十年

匿名函数

 

概念:

1.什么是匿名函数:

  def 定义的是有名函数:特点是可以通过名字重复调用

    def func(): # func=函数的内存地址

  匿名函数就是没有名字的函数:特点是只能在定义时使用一次

2.为何要用匿名函数

  强调:

    匿名函数的定义就相当于只产生一个变量的值,而没有绑定任何名字,所以在定义完之后就会被回收,无法重复使用,只能在定义时使用一次

    (函数分为定义阶段和调用阶段,定义阶段已经将函数加载到内存)  

    应用:

    当某一个功能仅使用一次就没有再重复使用的必要了,就应该定义成匿名函数

3.如何用匿名函数

  lambda  x,y:x+y  ----->没有函数名,直接传参。省略return

匿名函数基本代码:

print(lambda x,y:x+y)
#<function <lambda> at 0x0000000001D11E18>

res=(lambda x,y:x+y)(1,2)#调用和传值
print(res)
#3

内置函数:字典包含两部分,要特殊对待

 

  正常情况下字典参与函数操作的都是键,函数返回的也是键。

  内置函数中key的作用是:让值进行比较,但是返回的是字典的键

max:

salaries = {
    'egon': 3000,
    'alex': 100000000,
    'wupeiqi': 10000,
    'yuanhao': 2000
}
nums=[10,-1,11,9,23]
print(max(nums))
print(max(salaries.values()))#返回的是最大数值
#返回最大工资对应的人名
salaries = {
    'egon': 3000,
    'alex': 100000000,
    'wupeiqi': 10000,
    'yuanhao': 2000
}
# key=函数的内存地址: 作用是控制函数的比较的值
1.多行代码实现   def func(k):   return salaries[k]   print(max(salaries,key=func)) #max函数的第二个参数key   # 1. 将可迭代对象salaries变成迭代器对象iter_obj   # 2. next(iter_obj)得到一个人名,然后将该人名当作参数传给key指定的函数,然后调用函数将函数的返回值当作比较依据   # 3. 比较大小,取出最大值对应的人名

2.单行代码实现
#通过匿名函数更加简洁的实现求极值 print(max(salaries,key=lambda k:salaries[k])) print(min(salaries,key=lambda k:salaries[k]))

sorted排序:

#以人名进行排序
nums=[10,-1,11,9,23] print(sorted(nums))  #默认从小到大排序 [-1, 9, 10, 11, 23] print(nums)  #不改变原值 salaries={ 'egon':3000, 'alex':100000000, 'wupeiqi':10000, 'yuanhao':2000 }
#
key=lambda k:salaries[k]--》定义一个匿名函数,salaries[k]可以取出字典对应的value,返回给匿名函数,即要比较的是值
print(sorted(salaries,key=lambda k:salaries[k])) 
print(sorted(salaries,key=lambda k:salaries[k],reverse=True))

map映射:

#在所有老师后加dsb
names = ['alex', 'wupeiqi', 'yuanhao', 'kevin', 'hu老师'] # 方式一:手动实现 new_names=[] for name in names: new_names.append(name+'dsb') print(new_names) # 方式二:列表生成式 new_names = [name + 'dsb' for name in names] print(new_names) # 方式三:map+匿名函数 res = map(lambda x: x + 'dsb', names) print(res)  #<map object at 0x000000000221F080> print(list(res)) #['alexdsb', 'wupeiqidsb', 'yuanhaodsb', 'kevindsb', 'hu老师dsb']

reduce合并:

# 方式一:手动实现
res=0
for i in range(101):
    res+=i
print(res)

# 方式二:列表生成式
print(sum([i for i in range(101)]))

# 方式三:reduce+匿名函数
from functools import reduce
print(reduce(lambda x,y:x+y,[i for i in range(101)],100))#5150
print(reduce(lambda x,y:x+y,[i for i in range(101)]))#5050
print(reduce(lambda x,y:x+y,['h','e','l','l','o'],'----------'))#----------hello

filter过滤:

#过滤出所有不以dsb结尾的老师姓名
names=['alex_dsb','wxx_sb','kevin_sb','hu_sb','egon'] # 方式一:手动实现 new_names=[] for name in names: if name.endswith('sb'): new_names.append(name) print(new_names) # 方式二:列表生成式 new_names=[name for name in names if name.endswith('sb')] print(new_names) # 方式三:filter+匿名函数 res=filter(lambda name:name.endswith('sb'),names) print(res)#<filter object at 0x0000000001EAC320> print(list(res))#['alex_dsb', 'wxx_sb', 'kevin_sb', 'hu_sb']

递归函数

 

概念:

1.什么是递归函数

  函数的递归调用时函数嵌套调用的一种特殊形式,

  特殊在调用一个函数的过程又直接或者间接地调用了该函数本身

  递归的本质就是一个循环的过程,

    但是递归必须满足两个原则:

      1.每进入下一层递归,问题的规模必须有所减少

      2.递归必须要有一个明确的结束条件或者说有一个明确的进入下一层递归的条件

    并且递归有两个明确的阶段

      1.回溯:一层一层的递归调用下去

      2.递推:在某一层结束掉递归,然后一层一层返回

2.为何要用递归

  在某些情况下,基于递归来使用重复的过程比while循环更加简单

直接调用和间接调用(非递归):

#直接
def f1():
    print('from f1')
    f1()
f1()

#间接
def f2():
    print('from f2')
    f1()
def f1():
    print('from f1')
    f2()
f1()

递归举例:

#推断第5个人的年龄,第4个人比第5个小两岁,。。。,第一个人为18岁
age(5)=age(4)+2 age(4)=age(3)+2 age(3)=age(2)+2 age(2)=age(1)+2 age(1)=18 age(n)=age(n-1)+2 # n>1 age(1)=18 # n=1
#用函数表示
def age(n):
if n == 1:
return 18
return age(n-1)+2

res=age(5)
print(res) #26

打印列表中的数字:

list1=[1,[2,[3,[4,[5,[6,[7,[8,[9,]]]]]]]]]
def func(l):
    for item in l:
        if type(item) is list:
            # 将item当作一个新列表传给功能本身
            func(item)
        else:
            print(item)
func(list1)

二分法:算法,高效解决问题的思路

#原始的方法:查询次数多
nums=[1,13,15,23,27,31,33,57,73,81,93,94,97,101] # 从小到大排列的数字列表
for num in nums:
    if 58 == num:
        print('find it')
        break
else:
    print('not exists')

#二分法:效率高,节省内存
nums = [1, 13, 15, 23, 27, 31, 33, 57, 73, 81, 93, 94, 97, 101]  # 从小到大排列的数字列表
def binary_search(find_num,nums):
    print(nums)
    if len(nums) == 0:
        print('not exists')
        return
    # 功能
    mid_index = len(nums) // 2
    if find_num > nums[mid_index]:
        # in the right
        nums=nums[mid_index+1:]
        # 重新运行功能,传入新列表
        binary_search(find_num,nums)
    elif find_num < nums[mid_index]:
        # in the left
        nums=nums[:mid_index]
        # 重新运行功能,传入新列表
        binary_search(find_num,nums)
    else:
        print('find it')

# binary_search(97,nums)
binary_search(95,nums)

 面向过程编程:

       核心是过程二字,过程指的是解决问题的步骤,即先干什么再干什么后干什么...

  基于该思想编写程序脑子里应该始终思考过程二字,就好比在设计一条流水线,是一种机械式的思维方式

    优点:复杂的问题的流程化,进而简单化
    缺点:扩展性差

 

posted @ 2018-10-10 17:32  ChuckXue  阅读(160)  评论(0编辑  收藏  举报