
(多重继承)[https://www.liaoxuefeng.com/wiki/0014316089557264a6b348958f449949df42a6d3a2e542c000/0014318680104044a55f4a9dbf8452caf71e8dc68b75a18000]
继承是面向对象编程的一个重要的方式,因为通过继承,子类就可以扩展父类的功能
问题
有以下四种动物
- Dog - 狗狗;
- Bat - 蝙蝠;
- Parrot - 鹦鹉;
- Ostrich - 鸵鸟;
如果按照哺乳动物和鸟类归类,我们可以设计出这样的类的层次
但是如果按照“能跑”和“能飞”来归类,我们就应该设计出这样的类的层次:
如果要把上面的两种分类都包含进来,我们就得设计更多的层次
- 哺乳类:能跑的哺乳类,能飞的哺乳类;
- 鸟类:能跑的鸟类,能飞的鸟类
类的层次就复杂了
如果要再增加“宠物类”和“非宠物类”,这么搞下去,类的数量会呈指数增长,很明显这样设计是不行的。
正确的做法是采用多重继承。首先,主要的类层次仍按照哺乳类和鸟类设计:
1 | class Animal(object): #动物类 |
然后我们提前定义好动物具备的行为1
2
3
4
5
6
7class Runnable(object):
def run(self):
print('Running...')
class Flyable(object):
def fly(self):
print('Flying...')
比如让狗继承动物类和跑的行为1
2class Dog(Mammal, Runnable): #此处继承了 哺乳类 和 跑的行为
pass
通过多重继承,一个子类就可以同时获得多个父类的所有功能
MixIn自由继承
在设计类的继承关系时,通常,主线都是单一继承下来的,例如,Ostrich继承自Bird。但是,如果需要“混入”额外的功能,通过多重继承就可以实现,比如,让Ostrich除了继承自Bird外,再同时继承Runnable。这种设计通常称之为MixIn
定制类
str
定义以下函数1
2
3
4class Student(object):
def __init__(self, name):
self.name = name
print(Student('Michael'))
输出 ><main.Student object at 0x109afb190>
后面序号是内存地址
为了得到对象内部具体数据 我们定义如下1
2
3
4
5
6class Student(object):
def __init__(self, name):
self.name = name
def __str__(self):
return 'Student object (name: %s)' % self.name
print(Student('Michael'))
输出 Student object (name: Michael)
iter
如果一个类想被用于for … in循环,类似list或tuple那样,就必须实现一个iter()方法,该方法返回一个迭代对象,
然后,Python的for循环就会不断调用该迭代对象的next()方法拿到循环的下一个值,直到遇到StopIteration错误时退出循环
Demo1
2
3
4
5
6
7
8
9
10
11
12
13
14
15class Fib(object):
def __init__(self):
self.a, self.b = 0, 1 # 初始化两个计数器a,b
def __iter__(self):
return self # 实例本身就是迭代对象,故返回自己
def __next__(self):
self.a, self.b = self.b, self.a + self.b # 计算下一个值
if self.a > 100000: # 退出循环的条件
raise StopIteration()
return self.a # 返回下一个值
for n in Fib():
print(n)
getitem
Fib实例虽然能作用于for循环,看起来和list有点像,但是,把它当成list来使用还是不行,
比如,取第5个元素:Fib()[5] 就会报错
要表现得像list那样按照下标取出元素,需要实现getitem()方法1
2
3
4
5
6
7
8class Fib(object):
def __getitem__(self, n):
a, b = 1, 1
for x in range(n):
a, b = b, a + b
return a
f = Fib()
print (f(0)) #1
list有切片
1 | class Fib(object): |
getattr
正常情况下,当我们调用类的方法或属性时,如果不存在,就会报错。比如定义Student类
1 | class Student(object): |
要想解决这个问题
1.在类中添加score这个属性
2.写一个getattr()方法,动态返回一个属性。修改如下
1 | class Student(object): |
call
创建一个实例的时候自动调用这个方法1
2
3
4
5
6
7
8
9class Student(object):
def __init__(self, name):
self.name = name
def __call__(self):
print('My name is %s.' % self.name)
s = Student('Michael')
s() # 输出 My name is Michael. 自动调用call方法
通过callable()函数可以判断一个对象是否可调用
1 | callable(max) #输出 True 可以调用 |
关于函数定制(官方文档)[https://docs.python.org/3/reference/datamodel.html#special-method-names]