python-函数(4)

内容概览

  • 多层装饰器
  • 有参装饰器
  • 递归函数
  • 算法之二分法

多层装饰器

"""多层装饰器的运行流程"""


def outer1(func1):  # func1 == inner2
    print('outer1运行')

    def inner1(*args, **kwargs):  # 2 调用function函数先执行之一段
        print('inner1运行')
        res = func1(*args, **kwargs)  # 3 调用inner2函数
        print('inner1结束')
        return res  # 11 函数执行结束

    return inner1


def outer2(func2):  # func2 == inner3
    print('outer2运行')

    def inner2(*args, **kwargs):  # 4 执行inner2
        print('inner2运行')
        res = func2(*args, **kwargs)  # 5 调用inner3
        print('inner2结束')
        return res  # 10 函数执行结束,返回上层函数

    return inner2


def outer3(func3):  # func3 == function
    print('outer3运行')

    def inner3(*args, **kwargs):  # 6 执行inner3
        print('inner3运行')
        res = func3(*args, **kwargs)  # 7 执行原function函数
        print('inner3结束')  
        return res  # 9 函数执行结束,返回上层函数

    return inner3

# 语法糖叠加的情况,会将最上边的值赋给原函数名
# 语法糖会将下边最近的函数名当做参数传给装饰的函数
@outer1  # 这里是最上边的语法糖了,所以将原函数名重新赋值 function = outer1(inner2)
@outer2  # 因为下边又返回了一个函数名,所以这句等同于 inner2 = outer2(inner3)
@outer3  # 等同于 inner3 = outer3(function) 先运行函数
def function():  # 8 执行function函数
    print('function') 


function()  # 1 这里相当于运行的是inner1
"""
outer3运行
outer2运行
outer1运行
inner1运行
inner2运行
inner3运行
function
inner3结束
inner2结束
inner1结束
"""

有参装饰器

如果需要在装饰器内添加额外的可以从外控制的变量,而且不改变愿代码的调用方式,就需要使用到有参装饰器了

def outer(func_name):  # 如果使用语法糖,这里不能添加变量,因为语法糖只能传入一个变量
	def inner(*args, **kwargs):  # 这里也不能传入变量,因为会改变函数的调用方式
		if data:  # 假设需要传入一个变量作为条件
			print('功能1')
			res = func_name()
			return res
	
	return inner


@outer
def fn():
	print('fn')

fn()
"""不能使用直接传参的方式,还能使用闭包函数来传参"""
def closure(data):  # 在这里将需要的一个或多个参数传入

	def outer(func_name):
	
		def inner(*args, **kwargs):
			if data:
				print('功能1')
				res = func_name()
				return res
		
		return inner

	return outer  # 将装饰器返回


@closure(123)  # 函数加括号优先运行函数,结果返回的是outer,这里就等同于@outer
def fn():
	print('fn')

fn()

递归函数

# 递归函数:函数直接或者间接的调用了自己
# 直接调用:
def fn():
	print('fn')
	fn()

fn()  # 在函数内无限调用自己, 最后超过了最大递归次数,报错

# 间接调用:
def fn1():
	print('fn1')
	fn2()

def fn2()
	print('fn2')
	fn1()

fn1()  # 两个函数相互无限调用,最后也会报错

"""
递归函数的正确使用方式
1.每调用一次都要比上一次简单
2.需要有一个明确的结束条件
"""
l1 = [1, [2, [3, [4, [5, [6, [7, [8, [9, [10, ]]]]]]]]]]
"""循环打印l1内所有数字"""
def get_num(vessel):
	for i in vessel:
		if i isinstance(i, int):
			print(i)
		else:
			get_num(i)

get_num(l1)

算法之二分法

算法是什么:算法就是解决问题的一种方法

"""二分法"""
l1 = [11, 23, 32, 45, 65, 78, 90, 123, 432, 467, 567, 687, 765, 876, 999, 1131, 1232]


def get_num(vessel, num):  # 将数据和选定的数字传入
    if len(vessel) == 0:  # 加入结束条件,如果列表长度为零还没有找到数字则结束
        print('没有这个数字')
        return

    num_index = len(vessel) // 2  # 整除得到中间数下标
    mediant = vessel[num_index]  # 通过下标获取数字
    if num > mediant:  # 判断指定数字是否大于中间数
        r_vessel = vessel[num_index + 1:]  # 获取中间数开始往后的所有数
        get_num(r_vessel, num)  # 传入剩下的数据值和选定的数字在执行一次函数
    elif num < mediant:  # 判断指定数字是否小于中间数
        l_vessel = vessel[:num_index]  # 获取从开头到中间数的所有数字
        get_num(l_vessel, num)  # 传入剩下的数据值和选定的数字在执行一次函数
    else:  # 如果不大不小,就代表找到数字了
        print('找到了', vessel[num_index])


get_num(l1, 999)
"""使用二分法,数据的数据值必须是有序的"""

练习

from functools import wraps
""""
1.尝试编写有参函数将多种用户验证方式整合到其中
直接获取用户数据比对
数据来源于列表
数据来源于文件
"""
user_info = ['jason', '321']
flag = ['0']


def outer(data_type):

    def judge(func):
        @wraps(func)
        def inner(*args, **kwargs):
            if flag[0] == '1':
                res = func(*args, **kwargs)
                return res
            username = input('username:').strip()
            password = input('password:').strip()
            if data_type == 'file':
                with open(f'userinfo.txt', 'r', encoding='utf8') as f:
                    for i in f:
                        dict_user, dict_pwd = i.split(',')
                        if dict_user == username and dict_pwd.rstrip() == password:
                            print('登录成功')
                            flag[0] = '1'
                            res = func(*args, **kwargs)
                            return res
                    else:
                        print('用户名或密码错误')
                        return

            elif data_type == 'list':
                if username == user_info[0] and password == user_info[1]:
                    print('登录成功')
                    flag[0] = '1'
                    res = func(*args, **kwargs)
                    return res
                else:
                    print('用户名或密码错误')
                    return

            else:
                if username == 'jason' and password == '123':
                    print('登录成功')
                    flag[0] = '1'
                    res = func(*args, **kwargs)
                    return res
                else:
                    print('用户名或密码错误')

        return inner
    return judge


choice_type = input('请选择验证方式:file/list/默认').strip()


@outer(choice_type)
def register():
    print('注册功能')


@outer(choice_type)
def login():
    print('登录功能')


@outer(choice_type)
def transfer():
    print('转账功能')


@outer(choice_type)
def withdraw():
    print('取款功能')


while True:
    func_dict = {'1': register, '2': login, '3': transfer, '4': withdraw}
    choise = input("""
               1.注册
               2.登录
               3.转账
               4.取钱
               请选择:""").strip()

    if choise in func_dict:
        func_dict[choise]()
    else:
        print('输入有误')

"""
2.尝试编写递归函数
推导指定某个人的正确年龄
eg: A B C D E  已知E是18 求A是多少
"""


def get_age(num):
    if num > 1:
        return 2 + get_age(num-1)
    else:
        return 18


print(get_age(5))
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值