定制类

形如__xxx__的变量或者函数名就要注意,这些在Python中是有特殊用途的。如__len__()方法是为了能让class作用于len()函数。

除此之外,Python的class中还有许多这样有特殊用途的函数,可以帮助我们定制类。

1、字符串定制__str__

首先顶一个一个Person 类,通过输出一个实例引入定制类的问题

#Coding = utf- 8

class Person(object):
    def __init__(self,name):
        self.name = name

print Person("rhx")
输出结果:<__main__.RoundFloatManual object at 0x00000000056A24E0>

其实本来是想输出实例化对象的,但是输出的确实地址信息,如何才能按照想要输出的形式显示呢?

此时就需要使用 __str__方法,返回一个字符串

#Coding = utf- 8

class Person(object):
    def __init__(self,name):
        self.name = name
    def __str__(self):
        return "Person object (name: %s)" %self.name
    
print Person("rhx")
输出结果:Person object (name: rhx)

但是知道,实例化对象时如果没有把这个实例对象保存到一个变量中,它很快就没有了,会被自动垃圾收集器回收,因为没有任何引用指向这个实例,所以对于Person('rhx')实例化对象,如果没有赋值给一个变量,实例创建时会给其分配一块内存,随即会释放掉它。在python命令行中如果直接调用实例化对象的变量,却也得不到想要的输出结果

>>> class Person(object):
...     def __init__(self,name):
...         self.name = name
...     def __str__(self):
...         return "Person object (name: %s)" %self.name
...
>>> p = Person("rhx")
>>> p
<__main__.Person object at 0x0000000004A829E8>

注意这里是在Python(command line),而第一个部分的IDE是pycharm.输出结果也是一个地址值,那如何得到期望的结果呢?

这是因为直接显示变量调用的不是 __str__() 而是 __repr__(),两者的区别是 __str__ 返回的是用户可见的字符串,而 __repr__ 返回的是开发者看到的字符串,也就是说 __repr__ 是为提调试服务的,即是在解释器中转储对象时,显示的是默认对象符号,因此如果要想修复它,只需要覆盖__repr__(),一个简单的办法是把__str__()的实现代码复制给__repr__(),但是要是__str_的实现方法存在问题,那么同样会把该bug带给__repr__,由于python中一切皆对象,因此可以将__str__()这个对象的引用赋值给__repr__,因此有:

>>> class Person(object):
...     def __init__(self,name):
...         self.name = name
...     def __str__(self):
...         return "Person object (name: %s)" %self.name
...     __repr__= __str__
...
>>> p = Person("rhx")
>>> p
Person object (name: rhx)

2、数值定制__add__

在字符串定制中,可以通过__str__进行有意义的输出显示,那对于类中的对象如何实现加法呢

class Time(object):
    def __init__(self,hr,min):
        self.hour = hr
        self.minute = min

    def __str__(self):
        return '%d:%d' % (self.hour,self.minute)
    __repr__ = __str__

mon = Time(10,20)
tue = Time(9,35)
print mon
print tue

print mon + tue
输出结果:
10:20
Traceback (most recent call last):
9:35
  File "F:/py_test/Python Advanced/RoundFloat2.py", line 25, in <module>
    print mon + tue
TypeError: unsupported operand type(s) for +: 'Time' and 'Time'

对象实例化的时候可以正常显示,但是无法运行加法运算。因此需要对其进行重载,重载较为简单,如+,只需要重载__add__()方法,那如何处理这个总数,因为相加之后是一个新的Time对象,并没有对mon和tue对象进行修改,因此需要创建一个新的对象并填入计算出来的总数

    def __add__(self, other):
        return self.__class__(self.hour+other.hour,self.minute+other.minute)

和普通情况一下,新的对象是通过调用类来实现的,不过这里不是使用的Time类,而是使用__class__,在类中,一般不直接使用类名,而是使用self的__class__属性,实例化self的那个类,并调用它。

此外还希望实现“原位”操作,如 += 的形式,在原来变量的基础上增加一个量,即是原位加法, __iadd__(),用来支持想 mon += tue的加法形式,重载一个 __i*__()方法额唯一秘密在它必须返回self,这样不难理解,在原来对象的基础上进行增量加法

    def __iadd__(self, other):
        self.hour += self.hour + other.hour
        self.minute += self.minute + other.minute

3、__iter__

        迭代器就是有一个next()方法的对象,而不是通过索引来计数,当一个循环机制(例如for...)需要下一项时,调用迭代器的next()方法就可以获得它,条目全部获取完之后,引发一个StopIteration异常,告诉外部调用者,迭代完成,对于如何创建一个迭代器呢,对于一个对象调用iter()就可以得到它的迭代器。如何在类中实现

class Fib(object):
    def __init__(self):
        self.a,self.b = 0,1   #菲波那切数列的前两项
    def __iter__(self):
        return self

    def next(self):
        self.a ,self.b = self.b,self.a + self.b  #数列迭代
        if self.b >= 5000:
            raise  StopIteration
        return self.a
for n in Fib():
    print n

4、元素获取__getitem__

虽然在上面实现了Fib类的迭代,使其用起来想list,但是要像list一样获取一个元素的时候,是否可以呢?

print "The second number of Fib: %d" %Fib()[7]
输出结果:
    print "The second number of Fib: %d" %Fib()[7]
TypeError: 'Fib' object does not support indexing

因此如果想要像list那样按照下表进行访问的话,需要实现 __item__()方法

    def __getitem__(self, item):
        a,b = 1,1
        for i in range(item):
            a,b = b,a + b
        return  a
这样就可以进行切片操作了




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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值