python关于装饰器使用的的问题,如何解决?

想用装饰器给这个函数计算运行时间,为什么一直不对啊,刚学,下面的错误也看不懂,谢谢各位

from time import *
def time_master(func):
    def time_(*args,**kwargs):
        print("开始调用程序")
        start=time()
        func(*args,**kwargs)
        stop=time()
        print("结束调用,共用时{:.5f}".format(stop-start))
    return time_

@time_master
def rabbit(m):
    if m<4:
        return m
    else:
        return rabbit(m-3)+rabbit(m-1)

print(rabbit(5))


错误显示
开始调用程序
开始调用程序
结束调用,共用时0.00000
开始调用程序
开始调用程序
结束调用,共用时0.00000
开始调用程序
结束调用,共用时0.00000
Traceback (most recent call last):
  File "C:\Users\13113\Desktop\递归.py", line 40, in <module>
    print(rabbit(5))
          ^^^^^^^^^
  File "C:\Users\13113\Desktop\递归.py", line 29, in time_
    func(*args,**kwargs)
  File "C:\Users\13113\Desktop\递归.py", line 38, in rabbit
    return rabbit(m-3)+rabbit(m-1)
                       ^^^^^^^^^^^
  File "C:\Users\13113\Desktop\递归.py", line 29, in time_
    func(*args,**kwargs)
  File "C:\Users\13113\Desktop\递归.py", line 38, in rabbit
    return rabbit(m-3)+rabbit(m-1)
           ~~~~~~~~~~~^~~~~~~~~~~~
TypeError: unsupported operand type(s) for +: 'NoneType' and 'NoneType'

进程已结束,退出代码1

代码修改如下, 增加 return,返回函数的执行结果

import time
from time import *


def time_master(func):
    def time_(*args, **kwargs):
        print("开始调用程序")
        start = time()
        res = func(*args, **kwargs)
        stop = time()
        print("结束调用,共用时{:.10f}".format(stop - start))
        return res

    return time_


@time_master
def rabbit(m):
    sleep(0.01)
    if m < 4:
        return m
    else:
        return rabbit(m - 3) + rabbit(m - 1)


print(rabbit(5))

  • 这个问题的回答你可以参考下: https://ask.csdn.net/questions/7622817
  • 这篇博客也不错, 你可以看下Python 编写一个学生类,要求有一个计数器,每次实例化后计数实例化了多少个学生【简单易懂,代码可以直接运行】
  • 你还可以看下python参考手册中的 python- 使用二进制数据记录格式
  • 除此之外, 这篇博客: Python网络爬虫数据抓取思路,静态与动态页面爬取思路,爬虫框架等中的   部分也许能够解决你的问题, 你可以仔细阅读以下内容或跳转源博客中阅读:
  • 大部分的数据都是直接写在静态文件上的,静态文件这里通常指的一定时间内不会变化的,不需要与后台进行交互的网页。

    1.首先确认抓取的数据是否存在于响应文件中

    2.分析页面结构,观察URL地址规律

        1)查看网页元素的布局,整体结构预览,常用控制台来分析

        2)查看在浏览网页(比如翻页)时元素结构是否发生变化

        3)查看页面跳转时URL地址是否变化(判断是否发生请求转发或重定向),如果有则去JS代码中找变化的原因

    3.开始编写代码进行数据抓取

    4.开始写自己的第一个爬虫程序

    Python爬虫入门,最简单的爬虫代码,网站如何判断是人为的操作还是爬虫程序的操作,为url参数中的中文参数进行编码,基于百度搜索的爬虫程序

    做完上面的案例后,可以再做一个案例练练手。Python爬虫小程序,爬取百度贴吧网页文件,新手练手的好案例

    5.多级页面爬取思路

    上面两个案例都是爬取一级页面的,一级页面指的是打开某个网页,仅仅对该网页上的内容做数据爬取,而二级页面就是在一级页面的基础上,你点击一个内容,这个内容往往是一个连接,它带你来到了另一个页面,这就是二级页面。在做爬虫时一般是先下载一级页面,这个页面没有我们要爬的数据,但是它包含了存储我们要的数据的网站的链接,收集所有链接后,我们拥有了所有的二级页面,也就拥有了所有数据,这时候你再到二级页面去爬数据即可。有二级页面也有三级页面四级页面,但是原理都是一样的。

    我们再来看看如何爬取二级页面的内容

    Python爬虫,4567电影网电影信息爬取,二级页面处理方案

    这一部分的数据不是存在响应内容中,而是存在Ajax的XML文件或者JS文件中,而且它随着你的操作而动态变化。

    1.如果发现想要的内容不再响应文件中,大可能性是使用Ajax动态生成的

    2.F12进入控制台抓包,刷新页面或执行某些行为,查看XHR异步加载的数据包内容

       1)GET请求:查看Request Headers请求头,查看请求头是如何做的,是否需要伪装请求头。

                               查看Query String Paramters,查看请求参数,这些参数多包含在URL中

       2)Post请求:查看Request Headers请求头,查看请求头是如何做的,是否需要伪装请求头。

                               查看FormData表单数据,看post发送请求时封装了哪些数据,这些数据哪些是动态的哪些是静态的,动态再进一步分析如何生成(主要通过分析JS代码)

    3.观察查询参数或者Form表单数据规律,如果需要进行进一步抓包分析处理,应当去分析JS文件

    4.使用request.get().json()获取json数据,利用列表或字典的方法提取数据

     

    1.将待爬取的URL放入队列中

    需要使用到的模块有:from queue import Queue

    2.多个线程从队列中取出地址,调用requests模块获取文件

    需要用到的模块有:from threading import Thread

    3.在进行I/O读写的时候注意加锁

    需要用到的模块有:from threading import Lock

    4.调取队列url地址的两种写法

    当队列值为空时,线程再去做请求会陷入阻塞,所以要为队列做判空操作或者加抛异常

    方式一:判断队列是否为空,避免线程堵塞

    while True:

        if not q.empty():

             url=q.get()

        else:

            break

    方式二:超时抛异常

     try:

        url=q.get(block=True,timeout=5)

        ....

     except Exception as e:

         break

    5.多线程争抢共同文件时的操作

    多线程写入文件时不加线程锁会导致一系列问题

    方法如下:

    from threading import Lock

    lock=Lock()

    lock.acquire() #加锁

    代码块

    local.relase() #释放

    案例:

    Python多线程爬虫,腾讯招聘网职位爬取程序,Ajax异步数据爬取模板

     

    此内容会在将来补上..

     

    pythoy一般用于解析页面的模块用re、lxml+xpath、json,以下是用法

    1.re

    re通过正则表达式来获取想要得到的内容,核心在于如何编写正则表达式

    python正则表达式re模块入门,贪婪匹配和非贪婪匹配,案例:猫眼电影TOP100信息提取

     

    2.lxml+xpath

    lxml+xpath是通过编写xpath,然后使用lxml来解析xpath进行匹配,需要知道xpath的规则(教程):

    Python常用插件类举,lxml+Xpath实现爬虫,使用Xpath爬取链家二手房源信息

     

    3.ajax/json 

    json一般是ajax动态数据,请求得到ajax响应内容后,将它json化,再进一步处理,如存库,存缓存

    Python多线程爬虫,腾讯招聘网职位爬取程序,Ajax异步数据爬取模板

     

    4.pyexecjs

    python爬虫程序之百度翻译,pyexecjs模块的用法(python里的js解析库)

  • 您还可以看一下 CSDN就业班老师的Python爬虫技术和浏览器模拟,验证码识别视频教程课程中的 网络爬虫概述小节, 巩固相关知识点
  • 以下回答由chatgpt基于相关博客总结生成:

    要计算函数的运行时间,可以使用装饰器来实现。下面是解决该问题的步骤:

    1. 创建一个装饰器函数 calculate_time,该函数接受一个函数作为参数,并返回一个新的函数。
    2. 在装饰器函数内部,定义一个新的函数 wrapper,用于包装原始函数。
    3. wrapper 函数内部,记录函数开始执行的时间。
    4. 调用原始函数,并将其返回值保存在一个变量中。
    5. 记录函数执行结束的时间,并计算函数的运行时间。
    6. 打印函数的运行时间。
    7. 返回原始函数的返回值。
    8. 在需要计算运行时间的函数上面添加 @calculate_time 装饰器。

    下面是具体的代码实现:

    import time
    
    def calculate_time(func):
        def wrapper(*args, **kwargs):
            start_time = time.time()
            result = func(*args, **kwargs)
            end_time = time.time()
            run_time = end_time - start_time
            print(f"函数 {func.__name__} 运行时间为:{run_time} 秒")
            return result
        return wrapper
    
    @calculate_time
    def get_data(url):
        # 函数的具体实现
        pass
    
    def main():
        for i in range(1, 2):
            url = "https://www.csflhjw.com/zhenghun/9.html?page={}".format(i)
            html_data = get_data(url)
    
    if __name__ == '__main__':
        main()
        document.save('demo.docx')
    

    将上述代码插入到原始代码中,即可实现计算函数运行时间的功能。当 get_data 函数被调用时,装饰器 calculate_time 会自动计算函数的运行时间并打印出来。

应该是 time.now(), time()就是创建一个对象, 当然都是0了

才发现这个是计算函数每次运行时间啊...有佬知道这种递归函数怎么改成计算总时间的吗(还是装饰器)