Python高阶基础之单继承下的属性查找

发布时间 2023-06-27 19:05:45作者: Way*yy

单继承下的属性查找

# 单继承就是一个类只继承一个类
例如:
	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']