有参装饰器与递归算法

有参装饰器

有参装饰器是装饰器的复杂版本,相比常规的装饰器增加了额外的形式参数来增加输入。

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循环

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值