单继承下的属性查找
# 单继承就是一个类只继承一个类
例如:
class A:
pass
class B(A):
pass
# 单继承下的属性查找
class Foo:
def index(self):
print('from Foo.index>>>>>')
def inner(self):
print('from inner>>>>>')
self.index()
class Bar(Foo):
def index(self):
print('from Bar.index>>>>>')
obj = Bar()
obj.inner() # obj.inner(obj)
# from inner
# from Bar.index
"""单继承下的属性查找顺序:先从对象自己的名称空间中查找,然后去产生这个对象的类中查找,最后在去继承的父类中查找"""
例二:
class Foo:
def __index(self): # >>>>>_Foo__index
print('from Foo.index>>>>>')
def inner(self):
print('from inner>>>>>')
self.__index() # >>>>>_Foo__index
class Bar(Foo):
def __index(self): # >>>>>_Bar__index
print('from Bar.index>>>>>')
obj = Bar()
obj.inner()
# from inner
# from Foo.index>>>>>
"""如果将属性隐藏起来,那么在定义阶段该隐藏属性就会发生变形,调用的self.__index()也发生了变形,所以只会找跟他相同的方法"""
多继承下的属性查找
# 一个类可以继承多个类
"""python支持多继承"""
例:
class A:
pass
class B:
pass
class(A,B):
pass
"""子类继承的基类,也可以继承其他的类"""
"""多继承下的属性查找分为:菱形查找和非菱形查找"""
# 菱形查找分为:经典类和新式类
经典类:按照深度优先查询
新式类:按照的广度优先查询
"""在Python3中都是新式类,所以,多继承下的属性查找,如果属性找不到了,就会按照广度优先查询"""
# 一般情况下,最好不使用多继承
深度优先 and 广度优先
# 单继承
class E:
def test(self):
print('from E')
class F:
def test(self):
print('from F')
class B(E):
def test(self):
print('from B')
class C(F):
def test(self):
print('from C')
class D:
def test(self):
print('from D')
class A(B, C, D):
# def test(self):
# print('from A')
pass
print(A.mro())
'''
[<class '__main__.A'>, <class '__main__.B'>, <class '__main__.E'>, <class '__main__.C'>, <class '__main__.F'>, <class '__main__.D'>, <class 'object'>]
'''
obj = A()
obj.test() # 结果为:from B
# 可依次注释上述类中的方法test来进行验证

如果继承关系为"菱形结构",那么经典类与新式类会有不同MRO,分别对应属性的两种查找方式:"深度优先和广度优先"
# 多继承经典类
class G: # 在python2中,未继承object的类及其子类,都是经典类
def test(self):
print('from G')
class E(G):
def test(self):
print('from E')
class F(G):
def test(self):
print('from F')
class B(E):
def test(self):
print('from B')
class C(F):
def test(self):
print('from C')
class D(G):
def test(self):
print('from D')
class A(B,C,D):
# def test(self):
# print('from A')
pass
obj = A()
obj.test() # 如上图,查找顺序为:obj->A->B->E->G->C->F->D->object
# 可依次注释上述类中的方法test来进行验证,注意请在python2.x中进行测试

# 多继承新式类
class G(object):
def test(self):
print('from G')
class E(G):
def test(self):
print('from E')
class F(G):
def test(self):
print('from F')
class B(E):
def test(self):
print('from B')
class C(F):
def test(self):
print('from C')
class D(G):
def test(self):
print('from D')
class A(B,C,D):
# def test(self):
# print('from A')
pass
obj = A()
obj.test() # 如上图,查找顺序为:obj->A->B->E->C->F->D->G->object
# 可依次注释上述类中的方法test来进行验证

### super关键字
```python
class People():
school = 'SH' # 严格依赖继承
def __init__(self, name, age, gender):
self.name = name
self.age = age
self.gender = gender
class Student(People):
def __init__(self, name, age, gender, course):
"""这个是指名道姓的调用方法,不依赖于继承"""
# People.__init__(self, name, age, gender) # 有什么特殊之处,
# super(Student, self) 返回的是一个特殊的对象,超级对象
# 这种写法是python2中的写法
# super(Student, self).__init__(name, age, gender)
# python3中的写法
super().__init__(name, age, gender)
"""super严格依赖继承"""
self.course = course
def choose_course(self):
pass
stu = Student('kevin', '19', 'male', 'python')
print(stu.__dict__)
# {'name': 'kevin', 'age': '19', 'gender': 'male', 'course': 'python'}
特殊情况:
搭配"mro"使用
class A:
def test(self):
super().test()
class B:
def test(self):
print('from B')
class C(A, B):
pass
c = C()
c.test() # from B
"""mro列表"""
# mro列表就是C类的属性查找顺序
"""
如果你继承的类中出现了super()关键字的用法,就要使用mro列表来查找属性
"""
print(C.mro()) # [<class '__main__.C'>, <class '__main__.A'>, <class '__main__.B'>, <class 'object'>]
多态与鸭子类型
多态与鸭子类型是面向对象编程中的两个重要概念。
1. 多态(Polymorphism):多态是指对象能够根据其所属的类别表现出不同的行为。同一方法名可以在不同的类中有不同的实现。通过多态,可以在不知道对象具体类型的情况下,调用其方法。
2. 鸭子类型(Duck Typing):鸭子类型是一种动态类型的概念,它关注的是对象的行为而不是类型本身。如果一个对象具有和鸭子一样的行为,那么它就可以被视为鸭子。即使对象的类型不同,只要它们具有相同的方法,就可以在代码中使用相同的方式来处理它们。
一 、
"""如何在父类里面强制限制子类中必须有speak功能"""
import abc # abstract 抽象的
# 这个类就变成了:抽象类
# 抽象类的特点:只能被继承,不能被实例化!
# 抽象类中的方法都是抽象方法,而抽象方法不再实现具体的功能,而是用来限制子类的行为
"""强制限制,这种方式是python不推荐的,python推荐的是鸭子类型"""
class Animal(metaclass=abc.ABCMeta):
@abc.abstractmethod # 抽象方法
def speak(self):
pass
class People(Animal):
def speak(self):
pass
class Dog(Animal):
def speak(self):
pass
class Pig(Animal):
def speak(self):
pass
obj = Dog()
obj.speak()
二 、鸭子类型
class Animal:
def sound(self):
pass
class Dog(Animal):
def sound(self):
print("Woof!")
class Cat(Animal):
def sound(self):
print("Meow!")
def make_sound(animal):
animal.sound()
dog = Dog()
cat = Cat()
make_sound(dog) # 输出:Woof!
make_sound(cat) # 输出:Meow!
在上面的代码中,Animal 是一个基类,Dog 和 Cat 是其子类。它们都有一个 sound() 方法,但具体的实现不同。通过调用 make_sound() 函数,我们可以在不知道具体对象类型的情况下,调用相应对象的 sound() 方法。这就是多态的体现。
组合
组合:就是一个对象拥有一个属性,该属性的值是另外一个对象
class Foo():
def __init__(self, m):
self.m = m
class Bar():
def __init__(self, n):
self.n = n
obj = Foo(10)
obj1 = Bar(20)
"""obj对象就是一个超级对象,通过一个对象可以得到另外一个对象的值"""
obj.x = obj1
# obj.x ---------> obj1
print(obj1.n)
# print(obj.x.n)
print(obj.x.n) # print(obj1.n)
练习:
class People:
def __init__(self, name, age, gender):
self.name = name
self.age = age
self.gender = gender
class Course:
def __init__(self, course_name, course_price, course_period):
self.course_name = course_name
self.course_price = course_price
self.course_period = course_period
python = Course("python", 10000, '6mon')
print(python.__dict__)
# {'course_name': 'python', 'course_price': 10000, 'course_period': '6mon'}
linux = Course("linux", 20000, '5mon')
print(linux.__dict__)
# {'course_name': 'linux', 'course_price': 20000, 'course_period': '5mon'}
class Student(People):
def __init__(self, name, age, gender, course=None):
if course is None:
course = []
super(Student, self).__init__(name, age, gender)
self.courses = course
stu = Student('kevin', '19', 'male')
stu.courses.append(python.course_name) # stu.courses ====> [python对象]
stu.courses.append(linux.course_name) # stu.courses ====> [python对象, linux对象]
print(stu.courses) # ['python', 'linux']