【Python044--魔法方法:简单定制】

一、简单定制

基本要求:

-- 定制一个计时器的类

-- start和stop代表开始计时和停止计时

-- 假设计时器对象t1,print(t1)和直接调用t1均显示结果

-- 当计时器未启动或停止计时时,调用stop方法会给予温馨的提示

-- 两个计时器对象可以相加:t1 + t2

-- 只能使用提供的有限资源完成

=====================================================

程序编写之前需要了解一下资源(知识点)

-- 使用time模块的localtime方法获取时间

-- time.localtime()返回struct_time的时间格式

-- 表现你的类:__str__ 和 __repr__

解释:

返回struct_time时间格式

 

__str__  和 __repr__

输入t1显示结果(显示字符串),要实现这个功能这时候就需要重写__str__ 和 __repr__方法

>>> class A:
    def __str__(self):
        return "I LOVE AI"

    
>>> a = A()
>>> print(a)
I LOVE AI
>>> class B:
    def __repr__(self):
        return " I LOVE AI"

    
>>> b = B()
>>> print(b)
 I LOVE AI
>>> 

#要想实现print(对象)或者直接调用对象,就必须使用__str__ 和__repr__方法

整体程序的代码

import time as t

class Mytimer():
    def __init__(self):
        #定义一个列表存放时间的单位,以便程序运行后输出的结果直接是带单位的结果:如:总共运行了:3秒
        self.unit = ['','','','小时','分钟','']
        self.prompt = '未开始计时!'
        self.lasted = []
        #self.start = 0
        self.begin = 0
        #self.stop = 0
        self.end = 0
        #这里特别需要注意,方法名和属性名不能定义成同一个名字,否则属性会覆盖方法
    
    #实现直接调用对象来输出内容
    def __str__(self):
        return self.prompt

    #__str__ 赋值给 __repr__
    __repr__ = __str__

    #两个对象相加
    def __add__(self,other):
        prompt = "总共运行了"
        result = []
        for index in range(6):
            result.append(self.lasted[index]+other.lasted[index])
            if result[index]:#如果result是空的话执行
                prompt += (str(result[index])+self.unit[index])
        return prompt
   
    #开始计时
    def start(self):#self表示对象的引用
        self.begin = t.localtime()
        self.prompt = '提示:请先调用stop()停止计时'
        print('计时开始...')

    #停止计时
    def stop(self):
        if not self.begin:
            print("提示:请先调用start()进行计时!")
        else:
            self.end = t.localtime()
            #结束计时时并进行计算,即对象.内部方法
            self._clac()
            print('计时结束!')
    
    #内部方法(_方法名),计算运行时间
    def _clac(self):
        #计算的结果放在一个列表里面
        self.lasted = []
        #定义一个提示的变量
        self.prompt = '总共运行了'
        #依次遍历localtime的索引
        for index in range(6):
            #用结束时间减去开始时间得到运行的时间,并把结果放到lasted[]列表内
            self.lasted.append(self.end[index]-self.begin[index])
            #把每一次计算的结果进行一次追加
            if self.lasted[index]: #当lasted为0时就不会执行if内的语句,而是执行下一轮的循环
                self.prompt += str(self.lasted[index])+self.unit[index] #运行时间+单位

        #为下一轮计时初始化变量
                self.begin = 0
                self.end = 0
                
        
  执行结果:
>>> t1 = Mytimer()
>>> t1.start()
计时开始...
>>> t1.stop()
计时结束!
>>> t1
总共运行了9秒
>>> t2 = Mytimer()
>>> t2.start()
计时开始...
>>> t2.stop()
计时结束!
>>> t2
总共运行了5秒
>>> t1+t2
'总共运行了14秒'
>>>   

 二、按照课中的程序,如果开始计时的时间是(2022年2月22日16:30:30)停止时间是(2025年1月23日15:30:30),那按照我们用停止时间减开始时间的计算方式就会出现负数,你应该对此做一些转换

import time as t


class MyTimer:

    def __init__(self):
        self.unit = ['', '', '', '小时', '分钟', '']
        self.borrow = [0, 12, 31, 24, 60, 60]
        self.prompt = "未开始计时!"
        self.lasted = []
        self.begin = 0
        self.end = 0

    def __str__(self):
        return self.prompt

    __repr__ = __str__

    def __add__(self, other):
        prompt = "总共运行了"
        result = []
        for index in range(6):
            result.append(self.lasted[index] + other.lasted[index])
            if result[index]:
                prompt += (str(result[index]) + self.unit[index])
        return prompt

    # 开始计时
    def start(self):
        self.begin = t.localtime()
        self.prompt = "提示:请先调用 stop() 停止计时!"
        print("计时开始...")

    # 停止计时
    def stop(self):
        if not self.begin:
            print("提示:请先调用 start() 进行计时!")
        else:
            self.end = t.localtime()
            self._calc()
            print("计时结束!")

    '''
    |-- print ("end+++", self.end[index],"\nbegin---", self.begin[index]) 打印出来理解end[index],begin[index]
    |--             for i in self.end:
                print ("====",i)    打印看self.end是如何的运行的
    '''

    # 内部方法,计算运行时间
    def _calc(self):
        self.lasted = []
        self.prompt = "总共运行了"
        for index in range(6):
            temp = self.end[index] - self.begin[index]
            print ("end+++", self.end[index],"\nbegin---", self.begin[index])
            print("temp:",temp)
            # for i in self.end:
            #     print ("====",i)
            print("\n")

            # 低位不够减,需向高位借位
            if temp < 0:
                # 测试高位是否有得“借”,没得借的话向再高位借......
                i = 1
                while self.lasted[index - i] < 1:
                    self.lasted[index - i] += self.borrow[index - i] - 1
                    self.lasted[index - i - 1] -= 1
                    i += 1

                self.lasted.append(self.borrow[index] + temp)
                self.lasted[index - 1] -= 1
            else:
                self.lasted.append(temp)

        # 由于高位随时会被借位,所以打印要放在最后
        for index in range(6):
            if self.lasted[index]:
                self.prompt += str(self.lasted[index]) + self.unit[index]

        # 为下一轮计时初始化变量
        self.begin = 0
        self.end = 0

t1 = MyTimer()
t1.start()
print("begin==",t1.begin)
t.sleep(5)
t1.stop()
#print("end==",t1.end)
print(t1)

执行结果:
计时开始...
begin== time.struct_time(tm_year=2018, tm_mon=11, tm_mday=2, tm_hour=16, tm_min=16, tm_sec=59, tm_wday=4, tm_yday=306, tm_isdst=0)
end+++ 2018 
begin--- 2018
temp: 0


end+++ 11 
begin--- 11
temp: 0


end+++ 2 
begin--- 2
temp: 0


end+++ 16 
begin--- 16
temp: 0


end+++ 17 
begin--- 16
temp: 1


end+++ 4 
begin--- 59
temp: -55


计时结束!
总共运行了5秒

三、相信大家已经意识到不对劲了:为毛一个月一定要31天?不知道又可能也是30天或者29天吗?(上一题我们的答案是假设一个月31天)

没错,如果要正确得到月份的天数,我们还需要考虑是否闰年,还有每月的最大天数,所以太麻烦了......如果我们不及时纠正,我们会在错误的道理上越走越远.......

所以,这一次,小甲鱼提出来了更加优秀的解决方案:用time模块的perf_counter()和process_time()来计算,其中perf_counter()返回计时器的精准时间(系统的运行时间);process_time()返回当前进程执行CPU的时间总和

题目:改进我们课堂中的例子,这次试用perf_counter()和process_time()作为计时器。另外增加一个set_timer()方法,用于设置默认计时器(默认是perf_counter(),可以通过此方法修改为process_time())

 

import  time as t

class Mytimer():

    def __init__(self):
        self.prompt = '未开始计时...'
        self.begin = 0
        self.end = 0
        self.lasted = 0.0
        self.default_timer = t.perf_counter

    def __str__(self):
        return self.prompt

    __repr__ = __str__

    def __add__(self, other):
        result = self.lasted + other.lasted
        prompt = '共运行了%0.2f秒'%result
        return prompt

    #开始计时
    def start(self):
        self.begin = self.default_timer()
        self.prompt = '提示:请先调用stop结束计时。'
        print('开始计时...')

    #结束计时
    def stop(self):
        if not self.begin:
            print("提示:请先调用start开始计时!")
        else:
            self.end = self.default_timer()
            self._clac()
            print("计时结束!")


    def _clac(self):
        self.lasted = self.end - self.begin
        self.prompt = "总共运行了%0.2f秒"%self.lasted
        print("end++",self.end,"\nbegin--",self.begin)
        print("process_time=",t.process_time(),"perf_counter=",t.perf_counter())

        self.begin = 0
        self.end = 0

    #设置计时器(time.per_counter()) 和(time.process_time())
    def set_timer(self,timer):
        if timer == 'process_time':
            self.default_timer = t.process_time()
        elif timer == 'per_counter':
            self.default_timer = t.perf_counter()
        else:
            print("输入无效:请输入per_counter()或者process_time()")

t1 = Mytimer()
t1.start()
t.sleep(5)
t1.stop()
print(t1)

执行结果:
开始计时...
end++ 79777.388179093 
begin-- 79772.38780172
process_time= 0.040435 perf_counter= 79777.388454339
计时结束!
总共运行了5.00秒

 四、既然咱都做到这一步,那不如深入一下,再次改进我们的代码,让它能够统计一个函数运行若干次的时间

要求一:函数调用的次数可以设置(默认是1000000次)

要求二:新增一个 timeing()方法,用于启动计时器

import time as t

class Mytimer():

    def __init__(self,func,number = 1000000):
        self.propmt = '未开始计时...'
        self.default_timer = t.perf_counter
        self.number = number  #函数调用的次数,默认是1000000
        self.lasted = 0.0
        self.func = func

    def __str__(self):
        return self.propmt

    __repr__ = __str__

    def __add__(self, other):
        result = self.lasted+other.lasted
        propmt = '共运行了%0.2f秒'%result
        return propmt


    #内部方法,计算运行时间
    def timer(self):
        self.begin = self.default_timer()
        for i in range(self.number):
            self.func()
        print("number=",self.number,"\nfunc=",self.func())
        self.end = self.default_timer()
        self.lasted = self.end - self.begin
        self.propmt = '共运行了%0.2f秒'%self.lasted



    #设置计时器(perf_counter和process_time)
    def set_timer(self,timer):
        if timer == 'perf_counter':
            self.default_timer = t.perf_counter()
        elif timer == 'process_time':
            self.default_timer = t.process_time()
        else:
            print("输入无效,请输入process_time或perf_counter")

def test():
    text = 'I love AI'
    char = 'o'
    for char in text:
        pass

t1 = Mytimer(test)
t1.timer()
print(t1)

t2 = Mytimer(test,1000000)
t2.timer()
print(t2)

print(t1+t2)

执行结果:
number= 1000000 
func= None
共运行了0.30秒
number= 1000000 
func= None
共运行了0.27秒
共运行了0.57秒

 

转载于:https://www.cnblogs.com/frankruby/p/9873801.html

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值