【搬家】【Python】一瞥 Python 定制类的强大功能

本文最早于 2014年1月1日于本人个人博客(http://mooowooo.tk)发表,现博客搬家至此,转载请注明出处。


这篇是对 Python 里关于定制类部分学习后的一个简单总结,主要是通过例子来告诉大家定制类的强大。关于定制类的知识,我是在《Python 核心编程》里的 13.13 节学习的。书中有一个关于时间计算的例子,原书例子的代码我就不放上来了,有兴趣的朋友可以去找到本书来学习,我这里给出我对这个例子的修改和分析,来告诉大家为什么我说定制类十分强大。

Talk is week, let me show you my code.

class TimeCount(object):

    def __init__(self, minutes = 0, hours = 0, days = 0):
        if days <> 0 :
        self.days = days
        if hours < 24 and hours >= 0 :
            self.hours = hours
        elif hours >= 24 :
            self.days += hours / 24
            self.hours = hours % 24
        elif hours < 0 :
            self.hours = 0

        if minutes < 60 and minutes >= 0 :
            self.minutes = minutes
        elif minutes >= 60 :
            self.hours += minutes / 60
            self.minutes = minutes % 60
        elif minutes < 0 :
            self.minutes = 0

    def __str__(self) :
        return '%d days %d hours %d minutes' % (self.days, self.hours, self.minutes)

    __repr__ = __str__

    def __add__(self, other) :
        return self.__class__(self.minutes + other.minutes, self.hours + other.hours, self.days + other.days)

    def __iadd__(self, other) :
        self.days += other.days
        self.hours += other.hours
        self.minutes += other.minutes
        return self

    def __div__(self, other):
        return 'Error !'

if __name__ == '__main__':
    a = TimeCount(10, 2, 3)
    b = TimeCount(7, 4)
    c = TimeCount(175, 69)

    print a
    print b
    print c
    print a + b
    print a + c
    print a += c
    print b < c
    print a / c
    #print b % c

这段代码很简单,写得也很丑陋,不过已经足够表达 Python 里定制类的强大了。首先,我们创建了一个名为 TimeCount 的类,在实例化时,根据其传入的参数数量和每个参数的进制计算方式,为该实例计算出 最合理的表现形式。比如,在实例化 a b c 3个实例后,将其打印到屏幕上的效果是:

3 days 2 hours 10 minutes
0 days 4 hours 7 minutes
2 days 23 hours 55 minutes

跟之前实例化时传入的参数并不相同,因为在 __init__ 函数里,我们对传入的参数进行了进制换算和进位。当然,这并不是我们要讲的 Python 定制类的厉害之处。真正厉害的地方在下面的两句 a + ba + c

当我们在执行到 print a + b 时,Python 了解到,a 实例的值为 3 days 2 hours 10 minutesb 实例的值为 0 days 4 hours 7 minutes。因为我们在类中对 + 操作做了重载,所以 Python 计算出最终结果是 3 days 6 hours 17 minutes,于是 Python 就顺利将该结果打印到了屏幕上。

同理,在计算 print a + c 时,因为实例 c 在实例化时已经经过换算得到他的值为 2 days 23 hours 55 minutes,那么与 a 做计算时得到的结果是什么呢?最开始,我以为 Python 会笨笨的得到 5 days 25 hours 65 minutes 的错误结果。但是没想到,Python 直接给出了 6 days 2 hours 5 minutes 的正确答案。这一下子让我想到,之前学习 Common Lisp 时,看到过的一个小彩蛋,就是在 Common Lisp 里的 FORMAT 指令可以将一个随意输入的数字转换成为英文标准写法[1]。虽然这两个东西想起来好像没什么联系,但是一下子激发了我一窥究竟的欲望。于是打上断点——对了,我用的是 PyCharm,强烈推荐各位写 Python 的朋友试试,记得付费买正版——点击 debug ,开始一步步查看计算过程。

原来,Python 在计算时并不是讲两个实例的值单纯的加总后输出,而是调用 __init__ 创建一个——原谅我不知道怎么称呼——匿名实例。并将两个实例的值加总后传入进行进制换算。并把计算的结果输出,然后就丢弃掉这个临时创建的匿名实例释放资源。所以,当计算逻辑准确无误的写到 __init__ 中时,Python 总能给出正确的结果。想调戏 Python 对我来说还为时尚早。

同样的,因为我们也对 += 操作符进行了重载,所以 下面一句 print a += c 也会得出相同的结果,只是这个结果被赋值给了实例 a,同时计算过程也略有不同,有兴趣的朋友可以自己去 debug 一下。

我不知道其他 OO语言 是否也有此特性 因为还没去实验,不过回头想想,其实也并不是多么神奇的东西,一句话概括就是:申请了对用户不可见的匿名实例参与计算并得出当前算法下的正确结果。

大概应该就是这么回事,如有错漏,还望各位看官指出。

[1]: 比如输入 format nil "-r" 1606938044258990275541962092 你将得到 one octillion six hundred six septllion nino hundred thirty-eight sextillion forty-four quintillion two hundred fifty-eight quadrillion nine hundred ninety trillion two hundred seventy-five billion five hundred forty-one million nine hundred sixty-two thousand ninety-two 这个答案,数一数,绝对正确。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值