Python开发day19封装,多态,多继承,函数重写,迭代器(高级)

Day19笔记

用于类的函数

Issubclass(cls,class_or_tuple)

 

意义

判断一个类是否继承自其它的类,如果此类clsclasstuple中的一个派生子类,则返回 True, 否则返False

实例:

class A:

    pass

class B(A):

    pass

class C(B):

    pass

print(issubclass(C, B)) # True

print(issubclass(B, C))  # False

print(issubclass(bool, (C, B, A, int)))  # True

 

 

 

 

 

 

 

 

 

 

 

 

封装

Enclosure

意义

封装是指隐藏类的实现细节,让使用者不用关心这些细节

封装的目的是让使用中通过尽可能少的方法(或属性)操作对象

私有属性和方法

Python类中以双下划线'- -’)开头,不以双下划线结尾的标识为私有成员,私有成员只能用此类的方法进行访问和修改

示例:

class A:

    def __init__(self):

        self.__p1 = 100  # 创建私有属性,此属性在类外无法访问

    def __m1(self):  # 私有方法

        print("__m1 私有方法被调用")

    def infos(self):

        print("A类的infos访问的__p1属性是:", self.__p1)

        self.__m1()  # 调用自己的私有方法

    

a = A()

# print(a.__p1)  # 出错

a.infos()

# a.__m1()  # 当前主模块不能调用A类的私有方法

多态

字面意思

多种状态

状态

静态(编译时状态)

动态(运行时状态)

多态意义

多态是指在有继承/派生基类对象的类中,调用基类对象的方法,实际能调用子类的覆盖方法的现象叫动态

说明

多态调用的方法与对象相关,步与类型相关

Python全部对象都只有运行时状态(动态)

没有“c++语言”里的编译时状态(静态)

示例

class Shape:

    '''图形'''

    def draw(self):

        print("Shapedraw()被调用")

class Point(Shape):

    def draw(self):

        print("正在画一个点")

class Circle(Point):

    def draw(self):

        print("正在画一个圆")

def my_draw(s):

    s.draw()#S.draw调用谁是在运行时由s的类型动态决定

            #此处显示出运行时状态

Shape1 = Circle()

Shape2 = Point()

my_draw(Shape1)

my_draw(Shape2)

 

面向对象的编程语言的特征

(1) 封装 2)继承/派生 (3)多态

多继承

Multiple inheritance

 

意义

多继承是指一个子类继承自两个或两个以上的基类

语法

Class 类名(基类名1,基类名2…)

说明

一个子类同时继承自多个父类,父类中的方法可以同时被继承下来,如果两个父类中有同名的方法,则在子类中又没有覆盖,此方法时,调用结果难以确定

多继承的问题(缺陷)

(1) 标识符(名字空间)冲突的问题

 

(2) 要谨慎使用多继承

示例:

#q写一个类

class A:

    def m(self):

        print("A.m()被调用")

#w写一个类

class B:

    def m(self):

        print("B.m()被调用")

#e感觉qw写的两个类自己可以用

class AB(A,B):

    def m(self):

        print("AB.m被调用")

ab = AB()

ab.m()#AB类没有覆盖父类的方法时会出现冲突问题

多继承的MROMethod Resolution Order)问题

类的__mro__属性:

 作用: 用来记录属性(或方法)的查找顺序

钻石继承

示例: 面试题   

class A:

    def go(self):

        print('A')

class B(A):

    def go(self):

        print('B')

        super(B, self).go()  # C

class C(A):

    def go(self):

        print('C')

class D(B, C):

    def go(self):

        print('D')

        super().go()  # B

d = D()

d.go()  # 'D'

函数重写 overwrite

 

意义

在自定义的类内添加相应的方法,让自定义的类生成的对象(实例)在内建对象一样进行函数操作

对象转字符串函数

repr(x) 返回一个能代表此对象的表达式字符串,通常:

   evalreprobj)) = obj

对象转字符串函数的重写方法

Repr()函数的重定方法

Def__repr__(self):

    …

   Return 字符串

Str()函数的重写方法:

Def__str__(self):

    …

Return 字符串

 

Strobj)函数调用

说明

1. strobj)函数先查找obj.__str__()方法,调用此方法并返回结果

2. 如果obj.__str__() 方法不存在

则调用obj.__repr__()方法并返回结果

3. 如果obj.__repr__方法不存在

则调用object类的__repr__实例方法显示<__main__.MyNumber object at xxx>

示例

对象转字符串函数的重写方法

class MyNmber:

    def __init__(self,value):

        self.data = value

    def __str__(self):

        print('正在调用__str__方法,转为普通字符串')

        s = '自定义数据%d' %self.data

        return s

    def __repr__(self):

        return'MyNmber(%d)' % self.data

n1 = MyNmber(100)

print(str(n1))

print(repr(n1))

# 结果为:

# 正在调用__str__方法,转为普通字符串

# 自定义数据100

# MyNmber(100)

内建函数重写

 

__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 __abs__(self):

        '''此方法用于制定abs(obj) 函数取值时返回的结果'''

        if self.data < 0:

            # -self.data 创建一个新的对象返回回去

            t = MyInteger(-self.data)

            return t

        return MyInteger(self.data)

i1 = MyInteger(-100)

print(i1)  # 等同于print(str(i1))

n = abs(i1)

print(n)  # MyInteger(100)

i2 = MyInteger(200)

print(abs(i2))  # MyInteger(200)

数值转换函数重写

 

__complex__

complex (obj) 函数调用

__int__

int (obj) 函数调用

__float__

float (obj) 函数调用

__bool__

bool (obj) 函数调用

示例:

# 此示例示意自定义的对象转为python内键的数字类型

class MyNumber:

    def __init__(self, v):

        self.data = v

    def __repr__(self):

        return "MyNumber(%d)" % self.data

    def __int__(self):

        return int(self.data)

n1 = MyNumber(100.5)

n = int(n1)  # 自定义类型转为整数, 出错!!!

print(n)

布尔测试函数重写

 

格式

def __bool__(self):

     …

作用

用于boolobj)函数取值

用于if语句真值表达式中

用于whine语句的值表达式中

 

说明

1. 当自定义类内有__bool__(self)方法时,以此函数的返回值作为boolobj)的返回值

2. 当不存在__bool__(self)方法时,boolx)返回__len__(self)方法的返回值是否为零来测试布尔值

3. 当再不存在__len__(self)方法时,则直接返回True

示例

class MyList:

    def __init__(self, iterable=()):

        self.data = [x for x in iterable]

    def __repr__(self):

        return "MyList(%s)" % self.data

    def __len__(self):

        print("__len__被调用")

        return len(self.data)

    def __bool__(self):

        '''此方法用来制定一个bool(x) 返回的规则'''

        # 如果没有任何元素返回False

        print("__bool__方法被调用")

        if len(self.data) == 0:

            return False

        for x in self.data:

            if x:

                return True

        return False

myl = MyList([1, -2, 3, -4])

# myl = MyList()

print(myl)

print(bool(myl))  # False

print(len(myl))

myl1 = MyList([0, 0.0, False, None])    

print(bool(myl1))  # False

myl2 = MyList([0, 1, 2])

print(bool(myl2))  # True

迭代器(高级)

 

意义

可以通过next函数取值的对象就是迭代器

迭代器协议

指对象能够使用next函数获取下一个数据,在没有下一项数据时触发一个StopIteration异常来终止迭代的约定

迭代器的实现方法

__next__(self) 此方法用来实现迭代器协议

可迭代器的对象

指能用iterobj)函数返回迭代器对象

可迭代对象内部要定义__iter__(self) 方法来返回迭代器对象

可迭代对象的语法

形式

Class MyIterable:

Def__iter__(self):

    语句块

    Return 迭代器

# 此示例示意用自定义的类MyRange实现可迭代对象

# 用自定义的类MyIterator 实现迭代器

class MyIterator:

    def __init__(self, start, stop, step):

        # self.start变量用来记录迭代器的起始位置和当前位置

        self.start = start

        self.stop = stop

        self.step = step

    def __next__(self):

        '''此方法用于实现迭代器协议'''

        print("MyIterator.__next__方法被调用!")

        if self.start >= self.stop:  # 迭失终止条件

            raise StopIteration

        r = self.start  # 先将要返回的数存于变量r

        self.start += self.step  # 迭代器后移

        return r  # 送回给next(it) 调用

class 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类型创建的对象当做可迭代对象

        '''

        print("__iter__被调用")

        # 此处必须返回迭代器

        return MyIterator(self.start, self.stop, self.step)

L = [x for x in MyRange(5, 10)]

print(L)

print('----------------------------')

R = MyRange(5, 10, 2)

it = iter(R)  # R.__iter__

print(next(it))  # it.__next__

练习:

 写一个类MList 实现和list内几乎一样的功能

  MyList类内用列表来存储数据

class MyList:

    def __init__(self,iterable=()):

        self.data = [x for x in iterable]

    def append(self,v):

        ...用户添加数据...

   

L = MyList("ABCD")

print(L)#MyList(['A','B','C','D'])

L.append("E")

print(L)#MyList(['A','B','C','D','E'])

for x in L:

    print(x)#A B C D E

print("列表L的长度是:",len(L))#5

猜你喜欢

转载自blog.csdn.net/weixin_42312995/article/details/80849632