有参装饰器
有参装饰器是装饰器的复杂版本,相比常规的装饰器增加了额外的形式参数来增加输入。
def login():
username = input('输入用户名:')
pwd = input('输入密码:')
with open(r'user_info.txt', 'r', encoding='utf8') as f:
for line in f:
real_name, real_pwd = line.split('|')
if real_name == username and real_pwd == pwd:
print('登录成功')
else:
print('登录失败')
该代码的效果是从文件中获取用户名密码来判断是否登录成功,如果后期程序需要扩展获取来源,可以额外从程序中定义好的列表和字典中获取用户信息,应该如何添加装饰器呢?
首先先给登录函数外包装一个装饰器,装饰器用于添加额外功能,并把原函数改名成inner(内部函数)方便区分
def login(func_name):
def inner(*args, **kwargs):
username = input('输入用户名:')
pwd = input('输入密码:')
with open(r'user_info.txt', 'r', encoding='utf8') as f:
for line in f:
real_name, real_pwd = line.split('|')
if real_name == username and real_pwd == pwd:
print('登录成功')
else:
print('登录失败')
return inner
随后在外部再包一个函数,该函数用于添加多个输入数据来源。
def outer(condition):
def login(func_name):
def inner(*args, **kwargs):
uname = input('输入用户名:')
pwd = input('输入密码:')
if condition == '列表':
print('使用列表作为数据来源')
elif condition == '字典':
print('使用字典作为数据来源')
elif condition == '文件':
print('使用文件作为数据来源')
else:
print('方式错误')
return inner
return login
关于如何在新添加的多个区域查找,可以在装饰器语法糖的括号采用变量来输入
def outer(condition):
def login(func_name):
def inner(*args, **kwargs):
uname = input('输入用户名:')
pwd = input('输入密码:')
if condition == '列表':
print('使用列表作为数据来源')
elif condition == '字典':
print('使用字典作为数据来源')
elif condition == '文件':
print('使用文件作为数据来源')
else:
print('方式错误')
return inner
return login
ways = ['列表', '字典', '文件']
for i in ways:
@outer(i)
def index():
print('form index')
index()
随后补齐列表字典文件的登录程序代码
l1 = ['jason|123']
d1 = {
'1': 'jason|123'
}
def outer(condition):
def login():
def inner():
uname = input('输入用户名:')
pwd = input('输入密码:')
global logged
if condition == '列表':
user_data = '%s|%s' % (uname, pwd)
if user_data in l1:
print('登录成功 来源列表')
logged = True
else:
print('登录失败')
elif condition == '字典':
user_data = '%s|%s' % (uname, pwd)
if user_data in d1:
print('登录成功 来源字典')
logged = True
else:
print('登录失败')
elif condition == '文件':
with open(r'user_info.txt', 'r', encoding='utf8') as f:
for line in f:
real_name, real_pwd = line.split('|')
if real_name == uname and real_pwd == pwd:
print('登录成功 来源文件')
logged = True
else:
print('登录失败')
else:
print('方式错误')
return inner
return login
logged = False
ways = ['列表', '字典', '文件']
if logged == False:
for i in ways:
@outer(i)
def index():
print('form index')
index()
else:
print('登录失败')
递归函数
当函数内部有调用函数本身时,这个函数就称为递归函数。
def func():
a += 1
func()
func()
在多个函数中循环相互调用也可以称为递归函数。
def func1():
pass
func2()
def func2():
pass
func1()
func1()
相比while循环,递归函数必须设定终止循环的条件,否则会一直运行到python允许的循环上限1000次或者内存溢出。
while循环 | 用于条件判断 | 可以通过条件、break、continue结束 |
递归函数 | 用于一层层推导最终结果 | 只能手动设定终止循环的条件 |
严格意义上while与递归功能接近,但使用函数可以让代码更加简洁易懂。
例:循环打印l1内部的所有数值
l1 = [1, [2, [3, [4, [5, [6, [7, [8, [9, [10, ]]]]]]]]]]
def get_num(l1):
for i in l1:
if isinstance(i,int):
print(i)
else:
get_num(i)
get_num(l1)
算法
算法是解决问题的方法的概况,如果一类问题解决的代码结构类似,那么这个结构称为一个算法。
二分法
在一个列表/字典/元组/集合中查找一个数值时,先获取数据集中间那个数,然后判断中间的数据值与目标数据值的大小,随后以中间的数左侧或右侧开始下一轮循环直到找到目标数值。
像这样从中间开始一半一半查找数值的方法叫二分法。
l1 = [10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28]
def get_age(l1, target_num):
if len(l1) == 0: #当列表一直对半分到没有数值的时,0除2等于0,必须终止循环
print('未找到符合的年龄')
return
mid_index = len(l1)//2 #获取列表长度然后用2整除
mid_num = l1[mid_index]
if target_num > mid_num:
l1_right = l1[mid_index+1:]
print(l1_right)
get_age(l1_right, target_num)
elif target_num < mid_num:
l1_left = l1[:mid_index]
print(l1_left)
get_age(l1_left, target_num)
else:
print('目标年龄是', target_num)
target_num = input('输入目标年龄:')
target_num = int(target_num)
get_age(l1, target_num)
优点 | 当需要寻找的列表储存量十分大时,可以节约很多时间和内存空间 |
缺点 | 列表必须是有序的,且目标如果在列表的头/尾时效率不如for循环 |