PYTHON-匿名函数,递归与二分法,面向过程编程

"""
匿名函数
1 什么是匿名函数
def定义的是有名函数:特点是可以通过名字重复调用
def func(): #func=函数的内存地址
pass
匿名函数就是没有名字的函数:特点是只能再定义时使用一次

匿名
lambda x,y,z=1:x+y+z
#与函数有相同的作用域,但是匿名意味着引用计数为0,使用一次就释放,除非让其有名字
func=lambda x,y,z=1:x+y+z
func(1,2,3)
#让其有名字就没有意义

2 为何要用匿名函数
强调:
匿名函数的定义就相当于只产生一个变量的值,而没有绑定任何名字,
所以会在定义完之后就被回收,无法重复使用,只能在定义时使用一次
应用:当某一个功能仅使用一次就没有再重复使用的必要了,就应该定义成匿名函数

3 有名字的函数与匿名函数的对比
有名函数:循环使用,保存了名字,通过名字就可以重复引用函数功能

匿名函数:一次性使用,随时随时定义

4 如何用匿名函数
lambda x,y:x+y
应用:max,min,sorted,map,reduce,filter

"""
max,min----------------------------
lambda x,y:x+y,是一个内存地址
nums=[10,-1,11,9,23]
print(max(nums))
print(max(salaries.values()))
salaries = {
'egon练习': 3000,
'alex': 100000000,
'wupeiqi': 10000,
'yuanhao': 2000}
匿名函数key=函数的内存地址: 作用是控制max函数的比较的值
def func(x):
return salaries[x]

print(max(salaries,key=func))

1. 将可迭代对象salaries变成迭代器对象iter_obj
2. next(iter_obj)得到一个人名,然后将该人名当作参数传给key指定的函数,
然后调用函数将函数的返回值当作比较依据
3. 比较大小,取出最大值对应的人名
print(max(salaries,key=lambda k:salaries[k]))
print(min(salaries,key=lambda k:salaries[k]))

比较平方的大小max min
nums=[10,-1,11,9,23]
def func(x):
return x**2
res=max(nums,key=func)
print(res)


sorted----------------------------------
sorted排序:创建一个新的变量,不会改变原值。sort时会直接覆盖原值。
nums=[10,-1,11,9,23]
print(sorted(nums))
print(sorted(nums,reverse=True))

nums.sort()
print(nums)
nums.sort(reverse=True)
print(nums)

salaries={
'egon练习':3000,
'alex':100000000,
'wupeiqi':10000,
'yuanhao':2000}
print(sorted(salaries,key=lambda k:salaries[k]))
print(sorted(salaries,key=lambda k:salaries[k],reverse=True))


map映射,值的数量不变-----------------------
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)
print(list(res))


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))
print(reduce(lambda x,y:x+y,[i for i in range(101)]))
print(reduce(lambda x,y:x+y,['h','e','l','l','o'],'----------'))

filter筛选---------------------
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)
print(list(res))


=====================================
'''
递归与二分法

1. 什么是函数递归
函数的递归调用是函数嵌套调用的一种特殊形式,
特殊在调用一个函数的过程中又直接或者间接地调用了该函数本身

递归本质就是一个循环的过程,
但是递归必须满足两个原则:
1. 每进入下一层递归,问题的规模必须有所减少
2. 递归必须有一个明确的结束条件或者说有一个明确的进入下一层递归的条件
并且递归有两个明确的阶段
1. 回溯: 一层一层地递归调用下去
2. 递推: 再某一层结束掉递归,然后一层一层返回

回溯就是从外向里一层一层递归调用下去,
回溯阶段必须要有一个明确地结束条件,每进入下一次递归时,
问题的规模都应该有所减少(否则,单纯地重复调用自身是毫无意义的)

递推就是从里向外一层一层结束递归

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

3, 如何用

'''
def f1():
print('from f1')
f1()
f1()

def f2():
print('from f2')
f1()

def f1():
print('from f1')
f2()
f1()

递归举例:
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
else:
return age(n-1)+2

res=age(5)
print(res)


list1 = [1, [2, [3, [4, [5, [6, [7, [8, [9, ]]]]]]]]]

def func(lines):
for line in lines:
if type(line)is list:
func(line)
else:
print(line)
func(list1)

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] # 从小到大排列的数字列表

find_num = 97
def searh_num(find_num, nums):
print(nums)
if len(nums) == 0:
print('not find!')
return
mid_num = len(nums) // 2
if find_num>nums[mid_num] :
# print('right')
nums = nums[mid_num + 1:]
# 再次运行功能
searh_num(find_num, nums)
elif find_num <nums[mid_num]:
# print('left')
nums = nums[:mid_num]
# 再次运行功能
searh_num(find_num, nums)
else:
print('find it')

searh_num(97, nums)

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)


=============================

面向过程编程:

1、首先强调:
面向过程编程绝对不是用函数编程这么简单,
面向过程是一种编程思路、思想,而编程思路是不依赖于具体的语言或语法的。
言外之意是即使我们不依赖于函数,也可以基于面向过程的思想编写程序

2、定义
面向过程的核心是过程二字,过程指的是解决问题的步骤,即先干什么再干什么
基于面向过程设计程序就好比在设计一条流水线,是一种机械式的思维方式

优点:
复杂的问题流程化,进而简单化
缺点:
可扩展性差,修改流水线的任意一个阶段,都会牵一发而动全身

3、应用:扩展性要求不高的场景,典型案例如linux内核,git,httpd

4、举例
流水线1:
用户输入用户名、密码--->用户验证--->欢迎界面

流水线2:
用户输入sql--->sql解析--->执行功能

ps:函数的参数传入,是函数吃进去的食物,而函数return的返回值,
是函数拉出来的结果,面向过程的思路就是,把程序的执行当做一串首尾相连的功能,
该功能可以是函数的形式,然后一个函数吃,拉出的东西给另外一个函数吃,
另外一个函数吃了再继续拉给下一个函数吃。。。
原文地址:https://www.cnblogs.com/du-jun/p/9767788.html