用于类的函数:
issubclass(cls, cls_or_tuple) 判断一个类是否继承自某个类cls或tuple中的某些类中的一个类,如果是其中一个类的派生类,则返回True,否则返回False
示例:
class A:
pass
class B(A):
pass
class C(B):
pass
issubclass(C, B) # True
issubclass(B, A) # True
封装 enclosure
封装是指隐藏类的实现细节,让使用者不用关心类的实现细节
封装的目的是让使用者通过尽可能少的方法或属性来操作对象
私有属性和方法
python类中以双下划线('__') 开头,不以双下划线结尾的标识符为私有成员,私有成员只能使用方法来进行访问和修改
以'__' 开头的属性为私有属性
以'__' 开头的方法为私有方法
示例见:
# enclosure.py class A: def __init__(self): self.__p1 = 100 # 私有属性 print("self.__p1=", self.__p1) def __m(self): '''这是私有方法,此方法只能用此类的方法来调用,不能在其它地方调用''' print("A.__m方法被调用") def dowork(self): '此方法可以调用私有实例变量和实例方法' self.__m() print("dowork内.self.__p1=", self.__p1) class B(A): '''此类示意子类不能调用父类的私有成员''' def test(self): self.__m() # 出错 print(self.__p1) # 出错 a = A() # print(a.__p1) # 错误,不允许访问私有属性 # a.__m() # 无法调用 a.dowork() # a.test() # 出错
多态 polymorphic
字面意思: 多种状态
多态是指在有继承和派生关系的类中,调用基类对象的方法,实际能调用子类的覆盖方法的现象叫多态
状态:
静态(编译时确定的状态)
动态(运行时确定的状态)
说明:
多态调用的方法与对象相关,不与类型相关
python全部对象都只有"动态"没有"C++语言的"编译时状态(静态).
示例见:
# poly.py # 此示例示意多态中的动态 class Shape: '''此类描述图形类的共有属性和方法''' def draw(self): print("Shape.draw被调用") class Point(Shape): # 点类 def draw(self): print("Point.draw被调用") class Circle(Point): def draw(self): print("Circle.draw被调用") def my_draw(s): s.draw() # 此处显示出多态中的动态 s1 = Circle() s2 = Point() my_draw(s2) my_draw(s1)
面向对象的编程语言的特征:
封装
继承
多态
多继承 multiple inheritance
多继承是指一个子类继承自两个或两个以上的父类(基类)
语法:
class 类名(基类名1, 基类名2, ...):
...
说明:
1. 一个子类同时继承自多个父类,父类中的方法可以同时被继承下来
2. 如果两个父类中有同名的方法,而在子类中又没有覆盖此方法,调用结果难以确定
示列见:
# multi_inherit.py # 此示例示意多继承的语法 class Car: def run(self, speed): print("汽车以", speed, "km/h的速度行驶") class Plane: def fly(self, height): print("飞机以海拔", height, "米高度飞行") class PlaneCar(Car, Plane): """PlaneCar类同时继承自汽车类和飞机类""" p1 = PlaneCar() p1.fly(10000) p1.run(300)
多继承的问题(缺陷):
标识符冲突的问题,要谨慎使用多继承
示例见:
# multi_inherit2.py # 此示例示意多继承标识符冲突的问题 # 小李写了一个类A class A: def m(self): print("A.m()被调用") # 小张写了一个类B class B: def m(self): print("B.m()被调用") # 小王感觉小张和小李写的两个类自己都能用 class AB(A, B): pass # def m(self): # print("AB.m()被调用") ab = AB() ab.m() # 会???
多继承的 MRO(Method Resolution Order)问题
类的 __mro__ 属性
作用:
用来记录类的方法的查找顺序
示例见:
# mro.py # 此示例示意__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") super().go() # A class D(B, C): def go(self): print("D") super().go() # B d = D() d.go()
对象转字符串函数:
str(obj) 通过给定的对象返回一个字符串(这个字符串通常是给人阅读的)
repr(obj) 返回一个符合python语法规则,且能代表此对象的表达式字符串,通常这个字符串一定
是一个python表达式
通常:
eval(repr(obj)) == obj
例: s = "I'm a \"Teacher\""
s1 = str(s)
print(s1) # I'm a "Teacher"
s2 = repr(s)
print(s2) # 'I\'m a "Teacher"'
函数重写 overwrite
在自定义的类内加添相应的方法,让自定义的类创建的实例能够像内建对象一样进行内建的函数操作
对象转字符串函数的重写方法:
repr() 函数的重写方法:
def __repr__(self):
...
str() 函数的重写方法:
def __str__(self):
...
说明:
1. str(obj) 函数先查找obj.__str__()方法,调用此方法并返回结果
2. 如果obj.__str__()方法不存在,则调用obj.__repr__() 方法 并返回结果
3. 如果obj.__repr__方法不存在,则调用object类的__repr__实例方法显示<__main__.xxxxobject at 0xXXXXXXXX> 格式的字符串
示例见:
# mynumber.py class MyNumber(object): '''此类用于定义一个自定义的数字类型''' def __init__(self, value): self.data = value # data数据 def __str__(self): '''重写object类中的__str__(obj)''' print("MyNumber.__str__被调用") # return super().__str__() return "数字%d" % self.data n1 = MyNumber(100) s1 = str(n1) # s1 = n1.__str__() print(s1) n2 = MyNumber(200) print(str(n2)) # 数字200 # s2 = repr(n1) # print(s2)
# mynumber2.py class MyNumber(object): '''此类用于定义一个自定义的数字类型''' def __init__(self, value): self.data = value # data数据 def __str__(self): '''重写object类中的__str__(obj)''' print("MyNumber.__str__被调用") return "数字%d" % self.data def __repr__(self): return "MyNumber(%d)" % self.data n1 = MyNumber(100) s1 = str(n1) # s1 = n1.__str__() print(s1) s2 = repr(n1) # s2 = n1.__repr__() print(s2)
内建函数重写:
方法名
__abs__ abs(obj) 函数调用
__len__ len(obj) 函数调用
__reversed__ reversed(obj) 函数调用
__round__ round(obj) 函数调用
示例见:
# mylist.py class MyList: '''创建一个自定义列表类, 此MyList内部用列表来存储信息''' def __init__(self, iterable=()): self.data = [x for x in iterable] def __repr__(self): return "MyList(%s)" % self.data def __len__(self): '''方法必须反回整数''' return self.data.__len__() # return len(self.data) def __abs__(self): '''此方法实现把self的所有元素取绝对 值后返回全为正数的自定义列表MyList''' lst = [abs(x) for x in self.data] L = MyList(lst) # 创建新的MyList return L myl = MyList([1, -2, 3, -4]) print(myl) print("myl 的长度是:", len(myl)) # myl.__len__() myL3 = abs(myl) print(myL3) # MyList([1, 2, 3, 4]) # myl2 = MyList() # print(myl2)
数值转换函数重写
__complex__ complex(obj) 函数调用
__int__ int(obj)
__float__ float(obj)
__bool__ bool(obj)
示例见:
# myinteger.py class MyInteger: def __init__(self, value): self.data = int(value) def __int__(self): '''此方法必须返回整数''' return self.data def __float__(self): return float(self.data) a1 = MyInteger("100") i = int(a1) # 将MyInteger类型转为整数 print(i) f = float(a1) # a1.__float__() print(f) c = complex(a1) # a1.__complex__() print(c) b = bool(a1) # a1.__bool__() print(b)
布尔测试函数重写
方法名: __bool__
作用:
用于bool(obj)函数取值
用于 if 语句的真值表达式
用于while语句的真值表达式
说明:
1. 类内有__bool__(self) 方法,调用obj.__bool__方法取值
2. 当不存在__bool__(self) 方法,将用obj.__len__() 方法的返回值求布尔值
3.如果不存在__len__(self) 方法,则直接返回True
示例见:
# bool.py class A: # def __bool__(self): # print("__bool__方法被调用") # return False def __len__(self): print('__len__方法被调用') return 5 a = A() print(bool(a)) # False if a: print("a为真值") else: print('a为假值')
迭代器(高级)
什么是迭代器:
可以用next(it) 函数取值的对象,就是迭代器
迭代器协议
迭代器协议是指对象能够使用next函数获取下一项数据,在没有下一项数据时触发一个StopIteration异常来终止迭代的约定
迭代器协议的实现方法:
def __next__(self):
....
什么是可迭代对象
是指能用iter(obj) 函数返回迭代器的对象(实例)
可迭代对象的实现方法:
def __iter__(self):
...
return 迭代器
示例见:
# myiterator.py # 此示例示意将自定义的类定义为可迭代对象 class MyList: def __init__(self, iterable=()): self.data = [x for x in iterable] def __repr__(self): return "MyList(%s)" % self.data def __iter__(self): '''要求此方法必须返回迭代器''' return MyList_Iterator(self.data) # 返回迭代器 class MyList_Iterator: '此类用来创建能访问MyList类型对象的迭代器' def __init__(self, data): # 绑定可迭代对象的数据 self.data = data self.cur_index = 0 # 设置迭代器的起始位置 def __next__(self): '''此方法用来实现迭代器协议''' if self.cur_index >= len(self.data): raise StopIteration # 拿到当前索引指向的数 r = self.data[self.cur_index] # 将索引数指向下一个数 self.cur_index += 1 return r # 返回当前的数 L = MyList("ABCD") print(L) for x in L: print(x) # it = iter(L) # it = L.__iter__() # while True: # x = next(it) # x = it.__next__() # print(x)
练习:
3. 写一个类,Fibonacci实现迭代器协议,此类的对象可以作为可迭代对象生成相应的斐波那契数
1 1 2 3 5 8 13 ....
如:
class Fibonacci:
def __init__(self, n):
...
....
实现如下操作:
for x in Fibonacci(5)
print(x) # 1 1 2 3 5
L = [x for x in Fibonacci(50)]
print(L)
pring(sum(Fibonacci(100)))
class Fibonacci: def __init__(self, n): self.count = n def __iter__(self): return Fitreror(self.count) class Fitreror: def __init__(self, n): '''由迭代器来生成fibonaci数''' self.count = n self.a = 0 self.b = 1 self.cur_count = 0 # 当前生成个数 def __next__(self): if self.cur_count >= self.count: raise StopIteration v = self.a+self.b self.a, self.b = self.b, self.a+self.b self.cur_count += 1 return v for x in Fibonacci(5): print(x)