Python学习16——函数递归调用、匿名函数、模块
文章目录
- 函数递归调用
- 匿名函数
- 模块
函数递归调用
一、引用
函数的递归调用:就是在调用一个函数的过程中又直接或者间接的调用自己
示例:直接的调用自己
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())
print(sys.getrecursionlimit(2000))
所以:不应该无限递归调用下去,应该在满足某种条件下结束递归调用,然后返回
二、递归调用应该分为两个阶段
1、回溯(挖井) :一层一层的递归调用下去
2、递推(从井里跳出来):在满足某一条件的情况下结束回溯,然后开始向上一层一层返回
salary(5) = salary(4) + 10
salary(4) = salary(3) + 10
salary(3) = salary(2) + 10
salary(2) = salary(1) + 10
salary(1) = 18
n = 1 salary(n) = 18
n != 1 salary(n) = salary(n-1) + 10
def salary(n):
if n == 1:
return 18
return salary(n-1) + 10
res = salary(5)
print(res)
小案例1:
nums = [111, [222, [333, [444, [555, [666, [777]]]]]]]
def func(l):
for x in l:
if type(x) is list:
# 把自身代码重新调用
func(x)
else:
print(x)
func(nums)
小案例2:从小到大排列的一个数字列表,找数字
nums = [11, 13, 32, 47, 53, 73, 84, 91]
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, 15)
三元表达式: 表达式1 if 条件 else 表达式2
x = 111
y = 222
res = x if x > y else y
print(res)
匿名函数
匿名函数就是没有名字的函数
res = (lambda x,y:x+y)(1, 2)
print(res)
f = lambda x, y:x + y
print(f)
f(1,2)
特点:没有名字意味着只能用一次,用完之后就是垃圾,所以匿名函数只能用于临时使用一次的场景
salaries = {
'egon': 4.4,
'lqz': 3.3,
'yj': 2.2
}
def func(k):
return salaries
print(max(salaries, key=lambda k: salaries[k]))
print(min(salaries, key=lambda k: salaries[k]))
print(sorted(salaries, key=lambda k: salaries[k], reverse=True))
模块
1、什么是模块
模块就是一个功能的集合体,不是用来直接运行的,而是用来被导入使用的
模块分为三大来源:
(1)内置的模块
(2)第三方模块
(3)自定义模块
模块分为四种类别:
(1)一个py文件就是一个模块
(2)一个文件夹也是一个模块=》包
(3)已被编译为共享库或DLL的C或C++拓展
(4)使用C编写并链接到ptython中
2、为何要用模块
使用别人的模块:
拿来主义,提升开放效率
使用自定义模块:
(1)别人的代码不够用了,需要自己编写
(2)解决代码冗余
3、如何用模块
建一个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
导入模块
例子一:
文件名是spam.py,模块名则是spam
首次导入模块发生的事情
1、触发被导入的模块的运行,产生一个模块的名称空间,把模块中的名字都丢进去
2、会在当前执行文件中得到一个名字spam,该名字是指向被导入模块的名称空间的
之后的导入,名字spam直接引用首次导入产生的名称空间,不会再执行模块的内的代码了
import spam
import spam
import spamx=111
import spam
money = 2000
print(money)
print(spam.money)
def read1():
print('run.py-----read1')
spam.read2()
spam.change()
print(spam.money)
print(money)
一行导入多个模块
import spam,m1,m2,m3 # 不推荐
为导入的模块起别名
import dsfrefdgegdgregfdgwegsdfwe as sm
sm.xxx
例子二:
文件名是spam.py,模块名则是spam
x=111
# 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对应值的内存地址
from spam import money,read1,read2
from spam import money,read1,read2
from spam import money,read1,read2
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()
一行导入多个名字
from spam import money,read1
为导入的模块起别名
from spam import money as m
print(m)
from spam import *
from spam import *
print(money)
print(read1)
print(read2)
print(change)