python面向对象编程最大的乐趣在于“函数重写”,是得我们自定的对象,可以像python内建对象一样,进行函数操作。

一.  函数重写 overwrite

  • 什么是函数重写:在自定义的类内添加相应的特殊方法,让自定义的类生成的对象(实例)像内建对象一样进行函数操作。

二. 对象转字符串的重写方法

  • 对象转字符串函数:repr   &&   str
  1. repr(x):返回一个能代表此对象的表达式字符串,通常eval(repr(obj)) = obj;
  2. str(obj):通过给定对象返回一个字符串(这个字符串通常是给人阅读的);
  3. eval(str):将字符串当成表达式来运行

         

python 重写和方法的重载 python 重写函数_迭代

  • 对象转字符串的重写方法:(类似于java中重写toString()方法)
  1. repr()函数的重写方法

        def __repr__(self):
            ...
            return 字符串   # 返回的对象必须是字符串
     2. str()函数的重写方法:
        def __str__(self):
            ...
            return 字符串  # 返回的对象必须是字符串

     3. str(obj) 函数调用方法说明:

  1. str(obj) 函数先查找obj.__str__()调用此方法,并返回结果
  2. 如果obj.__str__这个方法不存在,则调用obj.__repr__()方法并返回结果;
  3. 如果obj.__repr__()方法不存在,则调用object类的__repr__实例方法打印<__main__.MyNumber object at xxx> 
"""对象转字符串的重写方法"""


class MyNumber:
    def __init__(self, value):
        self.data = value

    def __str__(self):
        """此方法继承自父类object"""
        return "自定义数据MyNumber(%d)" % self.data

    def __repr__(self):
        return 'MyNumber(%d)' % self.data


if __name__ == "__main__":
    print(MyNumber(100))
    print(MyNumber(100).__str__())
    print(str(MyNumber(100)))

    print(repr(MyNumber(200)))
    print(MyNumber(200).__repr__())

    print(eval(repr(MyNumber(300))))

运行结果:

python 重写和方法的重载 python 重写函数_特殊函数重写_02

三. 内建函数重写

重写方法

调用

__abs__

abs(obj)

__len__

len(obj)

__reversed__

reversed(obj)

__round__

round(obj)

示例:

class MyInteger:
    def __init__(self, v):
        self.data = v

    def __repr__(self):
        return 'MyInteger(%d)' % self.data

    def __str__(self):
        return '%d' % self.data

    def __abs__(self):
        """此方法用于制定abs(obj)函数取值时返回的结果"""
        if self.data < 0:
            return MyInteger(-self.data)
        return MyInteger(self.data)

    def __len__(self):
        return len(self.__abs__().__str__())

    def __reversed__(self):
        return MyInteger(self.data * -1)


print(MyInteger.__mro__)
num = MyInteger(-100)
# 等同于print(str(i1))
print("自定义的整数:{}".format(num))
# dir(object)没有__abs__方法
print("{}的绝对值为{}".format(repr(num), abs(num)))
print("{}的长度为{}".format(repr(num), len(num)))
print("{}反转后为{}".format(repr(num), repr(reversed(num))))

运行结果:

python 重写和方法的重载 python 重写函数_迭代_03

四. 数值转换函数重写

重写方法

函数调用

__complex__

complex(obj)

__int__

int(obj)

__float__

float(obj)

__bool__

bool(obj)

  • 布尔测试函数重写
  1. 格式:def __bool__(self):
  2. 作用:bool(obj)函数取值   |  if语句真值表达式  |  while语句的值表达式
  3. 说明:
  1. 当自定义类内有__bool__(self)方法时,以此方法的返回值作为bool(obj)的返回值;
  2. 当不存在__bool__(self)方法时,根据__len__(self)方法的返回值是否为0来测试bool值;
  3. 当再不存在__len__(self)方法时,返回True;
class MyList:
    """__bool__方法的重写方法及用法"""
    def __init__(self, iterable=()):
        self.data = [x for x in iterable]

    def __repr__(self):
        print('__repr__方法被调用')
        return 'MyList(%s)' % self.data

    def __len__(self):
        print('__len__方法被调用')
        return len(self.data)

    def __bool__(self):
        """此方法用来制定一个bool(x)返回的规则"""
        print("__bool__方法被调用")
        if len(self.data) == 0:
            return False
        for x in self.data:
            if x:
                return True
        return False


if __name__ == "__main__":
    myl = MyList([1, -2, 3, -4])
    print("my1:{}, {}".format(myl, bool(myl)))

    my2 = MyList([0, 0.0, False])
    print("my2:{}, {}".format(my2, bool(my2)))

运行结果1:

python 重写和方法的重载 python 重写函数_字符串_04

运行结果2:注释掉__bool__运行

python 重写和方法的重载 python 重写函数_字符串_05

运行结果3:注释掉__bool__和__len__方法运行

python 重写和方法的重载 python 重写函数_迭代器_06

五. 自定义类实现迭代器功能

  • 什么是迭代器:可以通过next函数取值的对象称为迭代器;
  • 迭代器协议:对象能够使用next函数获取下一个数据,在没有下一项数据时触发一个Stopiteration异常来终止迭代的约定; 

       

python 重写和方法的重载 python 重写函数_python 重写和方法的重载_07

  • 迭代器的实现办法:__next__(self) 方法用来实现迭代器协议;

        

python 重写和方法的重载 python 重写函数_迭代_08

  • 什么是可迭代对象:是指能用iter(obj)返回迭代器对象,可迭代对象内部要定义__iter__(self)来返回迭代器对象;

       

python 重写和方法的重载 python 重写函数_特殊函数重写_09

  • 可迭代对象的语法形式:

        class MyIterable:
            def __iter__(self):
                语句块
                return 迭代器

示例:

class MyIterator:
    """用自定义的类MyIterator实现迭代器"""
    def __init__(self, start, stop, step):
        # 用来记录迭代器的起始位置和当前位置
        self.start = start
        self.stop = stop
        self.step = step

    def __next__(self):
        """实现迭代器协议"""
        if self.start >= self.stop:
            raise StopIteration
        # 将要返回的数据存入一个变量
        r = self.start
        self.start += self.step  # 迭代器后移
        return r


class MyRange:
    """使用自定义的类MyRange实现可迭代对象"""
    def __init__(self, start, stop=None, step=1):
        if stop is None:
            stop = start
            start = 0
        self.start = start
        self.stop = stop
        self.step = step

    def __repr__(self):
        return 'MyRange(%d,%d,%d)' % (self.start, self.stop, self.step)

    def __iter__(self):
        """用于将MyRange类型创建的对象当做可迭代对象"""
        # 返回值必须为一个迭代器
        return MyIterator(self.start, self.stop, self.step)


if __name__ == "__main__":
    L = [x for x in MyRange(5)]
    print(L)

    R = iter(MyRange(1, 6, 2))
    while True:
        try:
            print(next(R))
        except StopIteration:
            break

运行结果:

python 重写和方法的重载 python 重写函数_迭代_10