就是在调用一个函数的过程中又直接或间接地调用自己
def foo():
print('hello')
foo()
foo()
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、递推(从井里往外跳):在满足某一条件的情况下结束回溯,然后开始向上一层层返回
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)
递归调用就是一个循环的过程,循环的次数取决于何时结束调用自身
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)
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
匿名函数即没有名字的函数,不能赋值给变量
def用于定义有名函数
# 以下不常用
# 正确匿名函数写法
res=(lambda x,y: x + y)(1,2)
print(res) # 3
#匿名函数错误写法:太过麻烦
f = (lambda x,y: x+y)
print(f) # at 0x00000190CEEB2EA0>
res = f(1,2)
print(res) # 3
**特点:**没有名字意味着只能用一次,用完之后就是垃圾,所以匿名函数只用于临时使用一次的场景
应用场景如下:
取薪资最高的人名
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))
模块就是一组功能的集合体,我们的程序可以导入模块来复用模块里的功能,不是用来直接运行。
模块分为三大来源:
1、内置的模块
2、第三方模块
3、自定义的模块
模块分为四种类别:
1、一个py文件就是一个模块,文件名是m.py,模块名叫m 如:spam.py为文件名,模块名则是spam
2、一个文件夹也是一个模块=》包(注:文件夹下有一个__init__.py文件)
3、已被编译为共享库或DLL的C或C++扩展
4、使用C编写并链接到python解释器的内置模块
# 使用别人的模块:
1、拿来主义,无需定义,可提升自己开发效率
# 自定义模块:
可以将程序各部分功能提取出来放到一模块中为大家共享使用
1、别人的功能不够用了,需要自己的去编写
2、解决代码冗余
## 首次导入模块会发生以下事
1、05模块 执行foo.py
2、05模块 产生foo.py名称空间,将foo.py运行过程中产生的名字都丢到foo的名称空间
3、在当前文件中产生的有一个名字foo,该名字指向自定义的foo.py模块
之后的导入,都是直接引用首次导入产生的foo.py名称空间,不会重复执行代码
# 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
# 文件名是spam.py,模块名则是spam
1、触发被导入的模块的运行,产生一个模块的名称空间,把模块中的名字都丢进去
2、会在当前执行文件中得到一个名字spam,该名字是指向被导入模块的名称空间的
之后的导入,名字spam直接引用首次导入产生的名称空间,不会再执行模块的内的代码了
import spam
import spam
import spam
import spam,m1,m2,m3 # 不推荐
导入模块顺序:内置模块、第三方模块、自定义模块
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,能够简洁代码
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()
from spam import money,read1
from spam import money as m
print(m)
from spam import *
# print(money)
# print(read1)
# print(read2)
print(change)