Day19笔记
用于类的函数
Issubclass(cls,class_or_tuple)
意义 |
判断一个类是否继承自其它的类,如果此类cls是class或或tuple中的一个派生子类,则返回 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("Shape的draw()被调用")
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感觉q和w写的两个类自己可以用
class AB(A,B):
def m(self):
print("AB.m被调用")
ab = AB()
ab.m()#当AB类没有覆盖父类的方法时会出现冲突问题
多继承的MRO(Method 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) 返回一个能代表此对象的表达式字符串,通常: eval(repr(obj)) = obj 缺 |
对象转字符串函数的重写方法 |
Repr()函数的重定方法 Def__repr__(self): … Return 字符串 Str()函数的重写方法: Def__str__(self): … Return 字符串 |
Str(obj)函数调用 说明 |
1. str(obj)函数先查找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): … |
作用 |
用于bool(obj)函数取值 用于if语句真值表达式中 用于whine语句的值表达式中 |
说明 |
1. 当自定义类内有__bool__(self)方法时,以此函数的返回值作为bool(obj)的返回值 2. 当不存在__bool__(self)方法时,bool(x)返回__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) 此方法用来实现迭代器协议 |
可迭代器的对象 |
指能用iter(obj)函数返回迭代器对象 可迭代对象内部要定义__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