面向对象(3)
issubclass 函数
issubclass(cls, class_or_tuple)判断一个类是否继承自其它的类,如果此类cls 是class 或 tuple中的一个派生子类,则返回True,否则返回False
示例:
class A:
pass
class B(A):
pass
class C(B):
pass
class D(B):
pass
issubclass(B,A) # True
issubclass(C,B) # True
issubclass(D,C) # False
issubclass(C,(int, str)) # False
封装 enclosure
封装是指隐藏类的实现细节,让使用者不关心这些细节封装的目的是让使用者通过尽可能少的使用实例变量名操作对象
私有属性和方法
python类中以上下划线'__'开头,不以双下滑先结尾的标识符为私有成员私有成员只能被方法调用,不能再子类或其他地方使用
私有成员有两种:
私有属性私有方法
示例:
class A:
def __init__(self):
self.__pl = 100 # 创建私有属性
def __m1(self):
print('A类的私有方法被调用!')
def test(self):
print(self.__pl) # 可以访问
self.__m1 #可以访问
a = A()
# print(a.__pi) # 出错,不可以访问
# a.__m1 # 出错,在类外不能调用类的私有方法
a.test() # 用方法来操作私有属性和私有方法
多态 polymorphic
字面意思:多种状态多态是指在有继承/派生关系的类中,调用基类对象的方法,实际能调用子类的覆盖方法的现象叫多态
多态说明:
多态调用方法与对象相关,不与类相关python的全部对象只有'运行时状态(动态)',没有'C++ / Java'里的'编译时状态(静态)'
多态示例:
class Shape:
def draw(self):
pass
class Point(Shape):
def draw(self):
print('正在画一个点')
class Circle(Point):
def draw(self):
print('正在画一个圆')
def my_draw(s):
s.draw() # 调用哪的方法呢?在运行时动态决定调用的方法
s1 = Circle()
s2 = Point()
my_draw(s1)
my_draw(s2)
面向对象的编程语言的特征:
封装
继承
多态
面向对象的语言:
C++/Java/Python/Swift/C#多继承:
多继承是指一个子类继承自两个或两个以上的基类语法:
class 类名(超类名1, 超类名1, ...):
pass
示例
# 此示例示意多继承
class Car:
def run(self, speed):
print('汽车以', speed, 'km/h的速度行驶')
class Plane:
def fly(self, height):
print('飞机以海拔', height, '米的高度飞行')
class PlaneCar(Car, Plane):
'''飞行汽车类,继承自Car和Plance'''
p1 = PlaneCar()
p1.fly(10000)
p1.run(299)
多继承的问题(缺陷)
标识符(名字空间)冲突的问题要谨慎使用多继承
示例:
#小张写的一个类A
class A:
def m(self):
print('A.m()被调用')
# 小李写的一个类B
class B:
def m(self):
print('B.m()'被调用)
# 小王感觉小张和小李写的两个了自己可以用
class AB(A,B):
pass
ab=AB()
ab.m() #请问调用谁? # A.m()被调用
多继承的MRO (method Resolution Order)问题
MRO:方法搜索顺序问题python2 使用深度优先算法
python3 使用广度优先算法
多继承的类使用 (类名.__mro__) 查看搜索顺序
函数重写 overwrite
什么是函数重写在自定义的类中,通过添加特定的方法,让自定义的类生成的对象(实例)能像内建对象一样进行内建函数操作
对象的字符串函数:
repr(obj) 返回一个能代表此对象的字符串,通常eval(repr(obj)) == objstr(obj) 通过给定的对象返回一个字符串(这个字符串通常是给人阅读的)
换句话说:repr(obj)返回的字符串是给python用的
str(obj) 返回的字符串是给人看的
重写方法:
repr(obj) 函数的重写方法 def __repr__(self)str(obj) 函数的重写方法 def __str__(self)
当对象没有__str__方法时,则返回__repr__(self)的值
示例:
# 此示例示意str(x)函数 和 repr(x)函数的重写方法
class MyNumber:
def __init__(self, value):
self.data = value
def __str__(self):
print('__str__方法被调用')
return '数字:%d' % self.data
def __repr__(self):
'''此方法共repr(obj)函数调用'''
return 'MyNumber(%d)' % self.data
n1 = MyNumber(100)
print(str(n1)) # 此句等同于print(n1)
print(n1)
print(repr(n1)) # 他会调用n1.__repr__()方法
内建函数重写
obj.__abs__() 方法对应 abs(obj)obj.__len__() 方法对应 len(obj)
obj.__reversed__() 方法对应 reversed(obj)
obj.__round__() 方法对应 round(obj)
示例
# 此示例示意abs(obj)函数的重写方法obj.__abs__()方法的使用
class Myinteger:
def __init__(self, value):
self.data = value
def __repr__(self):
return 'Myinterger(%d)' % self.data
def __abs__(self):
# return 'Myinterger(%d)' % abs(self.data)
if self.data < 0:
return Myinteger(-self.data)
return Myinteger(self.data)
def __len__(self):
'''len(x)函数规定只能返回整数值,因此此方法不能返回字符串等其他类型的值'''
return 1000000
I1 = Myinteger(-10)
print(I1) # <----此处等同于print(str(I1))
I2 = abs(I1)
print(I2)
print(len(I1))
数值转换函数重写
obj.__complex__() 对应 complex(obj)obj.__int__() 对应 int(obj)
obj.__float__() 对应 float(obj)
obj.__bool__() 对应 bool(obj)
示例:
# 此示例示意 数值类型转换函数重写
class MyNumber:
'''此类是自定义的类,用于表示自定义数字的类型'''
def __init__(self, v):
self.data = v
def __repr__(self):
return 'MyNumber(%s)' % self.data
def __int__(self):
return int(self.data)
n1 = MyNumber('100')
print('n1=', n1)
print(int(n1))
# print(float(n1)) # 需要实现__float__方法
布尔测试函数的重写
格式:def __bool__(self):
...
作用:
1、用于bool(obj)函数取值
2、用于if语句真值表达式中
3、用于while语句真值表达式中
说明:
布尔测试方法的查找顺序是__bool__方法,其次是__len__方法
如果没有以上方法则返回None
示例:
# 此示例示意 bool 真值测试函数的重写
class MyList:
'''
定义一个容器类,用于存储任意类型的数据
其内部的存储方式用list实现
'''
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):
print('__bool__方法被调用')
'''此方法用于bool(obj)函数取值,优先取此函数的返回值,此方法用于定义bool(obj)的取值规则'''
# 规则,所有元素的和为0,则返回False,否则返回True
return sum(self.data) != 0
myl = MyList([1, -2, 5, -4])
print(myl)
print('bool(myl) =', bool(myl)) # 优先调用__bool__方法,如果没有__bool__方法则调用__len__函数
if myl:
print('myl 的布尔值为True')
else:
print('myl 的布尔值为False')
迭代器(高级)
什么是迭代器
可以通过 next(obj)函数取值的对象,就是迭代器迭代器协议:
迭代器协议是指对象能够使用next函数获取下一项数据,在没有下一项数据时触发一个StopIteration异常来终止迭代的约定迭代器协议的实现方法:
在类内需要定义__next__(self)方法来实现迭代器协议语法形式:
class MyIteratot:def __next__(self):
迭代器协议
return 数据
什么是可迭代对象
是指能用iter(obj)函数返回迭代器的对象(实例)可迭代对象的内部定义__iter__(self)方法来返回迭代器对象
示例1
class MyList:
'''
定义一个容器类,用于存储任意类型的数据
其内部的存储方式用list实现
'''
def __init__(self, iterable):
self.data = [x for x in iterable]
def __repr__(self):
return 'MyList(%s)' % self.data
def __iter__(self): # 有此方法说明myl是迭代器
'''此方法把MyList类型的对象作为可迭代对象使用此方法需要返回迭代器'''
return MyIterator(self.data) # return 迭代器
class MyIterator:
'''此类定义一个迭代器类,用于生成能够访问MyList对象的迭代器'''
def __init__(self, lst_data):
print('迭代器已经创建')
self.data = lst_data # 绑定要访问的数据列表
self.cur_pos = 0 # 是指迭代器的其实位置为0
def __next__(self):
'''此方法用来访问可迭代对象的数据,如果没有数据时
触发StopIteration异常来通知调用者停止迭代,既迭代器协议'''
# 判断是否索引越界
if self.cur_pos == len(self.data):
raise StopIteration
index = self.cur_pos
self.cur_pos += 1 # 将当期位置向后移动准备下次获取
return self.data[index] # 返回当前位置的数据
myl = MyList([1, -2, 5, -4])
for x in myl:
print(x)
# 上面for语句等同于下面的语句
it = iter(myl)
while True:
try:
x = next(it)
print(x)
except StopIteration:
break
示例2
class MyList:
'''
定义一个容器类,用于存储任意类型的数据
其内部的存储方式用list实现
'''
def __init__(self, iterable):
self.data = [x for x in iterable]
def __repr__(self):
return 'MyList(%s)' % self.data
def __iter__(self):
self.cur_pos = 0 # 是指迭代器的其实位置为0
return self # return 迭代器
def __next__(self):
if self.cur_pos == len(self.data):
raise StopIteration
index = self.cur_pos
self.cur_pos += 1 # 将当期位置向后移动准备下次获取
return self.data[index] # 返回当前位置的数据
myl = MyList([1, -2, 5, -4])
for x in myl:
print(x)