【每日一练】python函数与装饰器

Python装饰器是一种用于修改函数或类的行为的语法结构。装饰器可以在不修改原始函数或类的情况下,为它们添加额外的功能。

使用装饰器的常见场景是在不改变原函数代码的情况下,给函数添加日志记录、性能统计、输入验证等功能。装饰器还可以用于授权、缓存、重试等功能。

装饰器通过在函数或类定义的上面添加@语法糖来使用。当定义了一个函数或类后,可以通过在其上面添加@装饰器名称,将装饰器应用到函数或类上。

下面是一个简单的装饰器示例:

python 复制代码
def log_decorator(func):
    def wrapper(*args, **kwargs):
        print(f"Calling function {func.__name__}")
        result = func(*args, **kwargs)
        print(f"Finished calling function {func.__name__}")
        return result
    return wrapper

@log_decorator
def add(a, b):
    return a + b

print(add(1, 2))

输出结果为:

复制代码
Calling function add
Finished calling function add
3

在上面的示例中,定义了一个装饰器log_decorator,它会在被装饰的函数调用前后打印日志。然后,通过@log_decorator将装饰器应用到add函数上。当调用add函数时,实际上是调用了log_decorator返回的wrapper函数,从而实现了打印日志的功能。

可以看到,装饰器可以方便地为函数添加额外的功能,而不需要修改原函数的代码。装饰器还可以带参数,用于传递给装饰器的函数或类。装饰器可以是函数形式的装饰器,也可以是类形式的装饰器。

使用递归实现斐波那契数列

python 复制代码
def f(n):
    if n < 2:
        return n
    else:
        return f(n - 1) + f(n - 2)


def fl(n):
    listF = []
    for i in range(n + 1):
        listF.append(f(i))
    print(listF)


fl(10)
复制代码
[0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55]

然而,这段代码有一个效率上的问题,即函数 f 使用递归的方式计算斐波那契数列,这种计算方式对于较大的 n 值非常低效,因为它会重复计算很多相同的值。

一个改进的方法是使用动态规划或者记忆化递归来避免重复计算。这里是一个使用记忆化的版本:

python 复制代码
def memoize(f):
    cache = {}
    def helper(x):
        if x not in cache:            
            cache[x] = f(x)
        return cache[x]
    return helper

@memoize
def f(n):
    if n < 2:
        return n
    else:
        return f(n-1) + f(n-2)

def fl(n):
    listF = []
    for i in range(n+1):
        listF.append(f(i))
    print(listF)

fl(10)

在这个版本中,我们添加了一个 memoize 装饰器来缓存已计算的结果,这样在递归调用时可以直接从缓存中获取结果而不需要重新计算。

请实现一个装饰器,把函数的返回值+100然后返回

python 复制代码
def x100(func):
    def inner(a, b):
        return func(a, b) * 100

    return inner


@x100
def add(a, b):
    return a + b


print(add(1, 2))
复制代码
300

请实现一个装饰器,通过一次调用使函数重复执行5次

python 复制代码
def run5(func):
    def inner():
        for i in range(5):
            func()

    return inner


@run5
def run():
    print("hello world")


run()
复制代码
hello world
hello world
hello world
hello world
hello world

请实现一个装饰器每次调用函数时,在调用函数时输出函数名字及调用函数的时间点

python 复制代码
import datetime


def name_time(func):
    def inner():
        func()
        print(
            "函数的执行时间点:", datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
        )
        print("函数名:", func.__name__)

    return inner


@name_time
def test():
    print("test函数执行。")


test()
复制代码
test函数执行。
函数的执行时间点: 2024-07-12 14:39:05
函数名: test

有一个计算两个数和的方法,为其添加一个确保两个参数都是int或float类型的装饰器,保证运算不会抛异常

python 复制代码
def check_num(func):
    def inner(n1, n2):
        if isinstance(n1, (int, float)) and isinstance(n2, (int, float)):
            return func(n1, n2)
        else:
            print("输入的参数类型有误!")

    return inner


@check_num
def add(n1, n2):
    return n1 + n2


add(3 ** (1 / 2), 3)
复制代码
4.732050807568877

有一个一次性录入人名并返回人名的方法(人名只考虑存英文),为其添加一个装饰器,使得处理后人名首字母一定大写

python 复制代码
# 首字母大写
def upper_name(func):
    def wrapper():
        name = func()
        return name.title()

    return wrapper


@upper_name
def get_name():
    name = input("name: ")  # owen
    return name


print(get_name())
复制代码
Owen

使用函数传参的方式实现去哪里旅游的功能,根据意向内容决定去玩什么

python 复制代码
def xuzhou():
    print("去徐州了。")


def lianyungang():
    print("去连云港了。")


def shanghai():
    print("去上海了。")


def trip(city):
    print("计划去旅游")
    city()
    print("旅游结束")


attraction = input("请输入要去的景点:")
if attraction == "云龙山" or attraction == "云龙湖":
    trip(xuzhou)
elif attraction == "花果山" or attraction == "水帘洞":
    trip(lianyungang)
elif attraction == "东方明珠" or attraction == "上海迪士尼":
    trip(shanghai)
else:
    print("没有这个景点。")
复制代码
计划去旅游
去连云港了。
旅游结束
相关推荐
用户8356290780513 小时前
Python 实现 PDF 文件加密与解密方法
后端·python
用户8356290780513 小时前
使用 Python 冻结与拆分 Excel 窗格教程
后端·python
花千烬11 小时前
crictl info 连不上 containerd 怎么办?endpoint、socket 与权限一次查清
云计算
你好潘先生12 小时前
别再记命令了,用 yeero do 说句人话就能跑脚本,而且不烧 token
服务器·python·命令行
Agent_大师12 小时前
WebSocket 行情重连成功,K线缺口不会自动消失
python
荣码12 小时前
LLM结构化输出:让AI返回JSON而不是废话,我踩了4个坑
java·python
copyer_xyf12 小时前
FastAPI 如何连接 MySQL
后端·python
apocelipes1 天前
常用编程语言和库的正则表达式性能对比
c语言·c++·python·性能优化·golang·开发工具和环境
用户8356290780511 天前
使用 Python 在 PDF 中创建与管理书签
后端·python
MeixianAgent1 天前
Python 回测数据入口怎么验?历史 K 线入库前先做 5 个检查
后端·python