函数递归调用、lambda自定义匿名函数、三元表达式、模块

一、函数的递归调用

就是在调用一个函数的过程中又直接或间接地调用自己

示例1:直接调用自己

def foo():
	print('hello')
	foo()

foo()

示例2:间接调用自己

def bar():
    print('from bar')
    foo()

def foo():
    print('hello')
    bar()

foo()

为何死递归会抛出异常

因为无限的递归会导致内存溢出,所以python设定了最大的递归层数

import sys
print(sys.getrecursionlimit()) #  1000
print(sys.setrecursionlimit(2000)) # None

所以:不应该无限递归调用下去,应该在满足某种条件下结束递归调用,然后返回

二:递归调用应该分为两个阶段

1、回溯(挖井):一层一层地递归调用下去
2、递推(从井里往外跳):在满足某一条件的情况下结束回溯,然后开始向上一层层返回

案例1(薪资):

salary(5) = salary(4) + 1000
salary(4) = salary(3) + 1000
salary(3) = salary(2) + 1000
salary(2) = salary(1) + 1000
salary(1) = 3000

salary(n) = salary(n-1) + 1000 # n > 1
salary(1) = 3000               # n = 1

def salary(n):
	if n == 1:
		return 3000
	return salary(n-1) + 1000

res = salary(4)
print(res)

总结:

递归调用就是一个循环的过程,循环的次数取决于何时结束调用自身

案例2(循环取出嵌套列表的值)

list1 = [1, [2, [3, [4, [5, [6, [7, [9, ]]]]]]]]
def func(l):
    for x in l:
        if type(x) is list:
            func(x)
        else:
            print(x)
func(list1)            

案例3(二分法)

方案一(for循环):整体遍历,效率低

nums = [-3, 1, 5, 7, 11, 13, 21, 37, 45]
find_num = 45
for num in nums:
    if find_num == num:
        print('find it')
    else:
        print('error')

方案二:二分法

算法:二分法查找适用于数据量较大时,但是数据需要先排好顺序

nums = [11, 13, 32, 47, 53, 73, 84, 91,101,111,222,333,444,5555]


def binary_search(l,find_num):
    print(l)
    if len(l) == 0:
        print('find_num not exists')
        return
    mid_index = len(l) // 2
    if find_num > l[mid_index]:
        right_l=l[mid_index+1:]
        binary_search(right_l,find_num)
    elif find_num < l[mid_index]:
        left_l=l[:mid_index]
        binary_search(left_l,find_num)
    else:
        print('find it')


binary_search(nums,85)
'''
运行结果:
[11, 13, 32, 47, 53, 73, 84, 91, 101, 111, 222, 333, 444, 5555]
[11, 13, 32, 47, 53, 73, 84]
[53, 73, 84]
[84]
[]
find_num not exists
'''

三、三元表达式

语法:条件成立时返回的值 if 条件 else 条件不成立时返回的值

def max(x,y):
	if x > y:
		return x
	else:
		return y
x = 1
y = 2
res = x if x > y else y
print(res) # 2

四、lambda自定义匿名函数

匿名函数即没有名字的函数,不能赋值给变量

def用于定义有名函数

# 以下不常用
# 正确匿名函数写法
res=(lambda x,y: x + y)(1,2) 
print(res) # 3

#匿名函数错误写法:太过麻烦	
f = (lambda x,y: x+y)
print(f) # <function <lambda> at 0x00000190CEEB2EA0>
res = f(1,2)
print(res) # 3

**特点:**没有名字意味着只能用一次,用完之后就是垃圾,所以匿名函数只用于临时使用一次的场景

!!匿名函数通常用于与其他函数配合使用

应用场景如下:
取薪资最高的人名

image-20200723193135927 image-20200723201847830
salaries = {
    "zegon": 3600,
    "lxx": 3000,
    "axx": 4000
}

# 取薪资最高的那个人的人名
#方式一(有名函数)
def func(k):
	return salaries[k]
# 比较的不是salaries迭代出的key,而是key=func指定的值作为比较依据,最终打印的还是salaries迭代的key
print(max(salaries,key=func)) # axx

# 方式二(匿名函数):
print(max(salaries,key=lambda k:salaries[k]))

print(min(salaries,key=lambda k:salaries[k]))
# 取出工资最低的人的人名
print(min(salaries,key=lambda k:salaries[k]))

# 按照工资高低给人名排序
# sorted(默认从低到高)(默认reverse=False)
print(sorted(salaries,key=lambda k:salaries[k]))

# 加上reverse=True(从高到底)
print(sorted(salaries,key=lambda k:salaries[k],reverse=True))

image-20200723104906358

五、模块

1、什么是模块

模块就是一组功能的集合体,我们的程序可以导入模块来复用模块里的功能,不是用来直接运行。

模块分为三大来源:

1、内置的模块
2、第三方模块
3、自定义的模块

模块分为四种类别:

1、一个py文件就是一个模块,文件名是m.py,模块名叫m 如:spam.py为文件名,模块名则是spam
2、一个文件夹也是一个模块=》包(注:文件夹下有一个__init__.py文件)
3、已被编译为共享库或DLL的C或C++扩展
4、使用C编写并链接到python解释器的内置模块

2、为何要用模块

# 使用别人的模块:
    1、拿来主义,无需定义,可提升自己开发效率
# 自定义模块:
	可以将程序各部分功能提取出来放到一模块中为大家共享使用
    1、别人的功能不够用了,需要自己的去编写
    2、解决代码冗余
  ## 首次导入模块会发生以下事
105模块 执行foo.py
205模块 产生foo.py名称空间,将foo.py运行过程中产生的名字都丢到foo的名称空间
3、在当前文件中产生的有一个名字foo,该名字指向自定义的foo.py模块
之后的导入,都是直接引用首次导入产生的foo.py名称空间,不会重复执行代码
image-20200723212610089

image-20200723211549925

3、如何用模块

3.1、import

# spam.py文件内的内容
print('from the spam.py')

__all__ = ['money', 'read1']

money = 1000


def read1():
    print('spam模块:', money)


def read2():
    print('spam模块')
    read1()


def change():
    global money
    money = 0

run1.py文件里的内容

x=111
import spam
money = 2000

print(money) # 2000 这里没有导入模块,打印的还是原文件的money
print(spam.money) # 1000 打印的是模块中的money

spam.read1() # spam模块: 1000

def read1():#用来显示下方调用的read2与这无关
    print('run1.py----read1')

spam.read2() #调用模块中的read2,因read2调用了read1
'''
运行结果:
spam模块
spam模块: 1000
'''

spam.change()
print(spam.money) # 0
spam.read1() # spam模块: 0
spam.read2() 
'''
运行结果:
spam模块
spam模块: 0
'''
print(money)#2000
3.1.1、首次导入模块发生的事情
# 文件名是spam.py,模块名则是spam
1、触发被导入的模块的运行,产生一个模块的名称空间,把模块中的名字都丢进去
2、会在当前执行文件中得到一个名字spam,该名字是指向被导入模块的名称空间的

之后的导入,名字spam直接引用首次导入产生的名称空间,不会再执行模块的内的代码了
import spam
import spam
import spam

image-20200724013949699
3.1.2、一行导入多个模块
import spam,m1,m2,m3  # 不推荐
导入模块顺序:内置模块、第三方模块、自定义模块
3.1.3、为导入的模块起别名
import spamasdfasfsadfadfasfd as sm
sm.xxx 

示例:
def sqlparse():
    print('from mysql sqlparse')
#oracle.py
def sqlparse():
    print('from oracle sqlparse')

#test.py
db_type=input('>>: ')
if db_type == 'mysql':
    import mysql as db
elif db_type == 'oracle':
    import oracle as db

db.sqlparse() # 不论调mysql or oracle都是调db,能够简洁代码

3.2、from …import…

3.2.1、首次导入模块发生的事情
from spam import money,read1,read2  # money=spam.money,read1=spam.read1,read2=spam.read2
1、触发被导入的模块的运行,产生一个模块的名称空间,把模块中的名字都丢进去
2、会在当前执行文件中得到名字
   money=模块spam中的money对应值的内存地址
   read1=模块spam中的read1对应值的内存地址
   read2=模块spam中的read2对应值的内存地址

run2.py 文件内容
from spam import money,read1,read2

print(money)
print(read1)
print(read2)


money=111
print(money)

money=2000
read1()

def read1():
    print('run.py read1')
read2()

3.2.2、一行导入多个名字
from spam import money,read1

3.2.3、为导入的模块起别名
from spam import money as m

print(m)

3.2.4、from spam import *
from spam import *
# print(money)
# print(read1)
# print(read2)
print(change)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值