45.Python super方法 & 类的组合使用 &类的多态性

1.调用父类方法

在子类中使用父类的方法,有两种方式:
1.指定类名
2.super()

1.1指定类名

继承或不继承都能使用,将对象作为参数传递给另一个类中,完成初始化.
class School:
    school = 'xxx'

    def __init__(self, name, age, gender):
        self.name = name
        self.age = age
        self.gender = gender


class Student(School):

    def __init__(self, name, age, gender, courses):
        # 指定名称访问
        School.__init__(self, name, age, gender)
        # 课程
        self.courses = courses

    # 学生信息
    def stu_info(self):
        print('< %s >' % self.courses)


# 教师类
class Teacher(School):
    school = School.school

    def __init__(self, name, age, gender, title):
        # 指定名称访问
        School.__init__(self, name, age, gender)
        # 教什么
        self.title = title

    # 老师的信息
    def Tea_info(self):
        print('< %s >' % self.title)


stu1 = Student('kid', 18, 'male', 'python')
tea1 = Teacher('xx', 30, 'male', 'python')
print(stu1.__dict__)
print(tea1.__dict__)
"""
{'name': 'kid', 'age': 18, 'gender': 'male', 'courses': 'python'}
{'name': 'xx', 'age': 30, 'gender': 'male', 'title': 'python'}
"""

image-20211206224613360

1.2super

调用super()放回一个特殊的对象,该对象专门用来应用父类的属性,依赖继承关系,严格按照mro的顺序查找.

Python2中: 
super(当前类名, self).__init__( 参数1, 参数2 ···) 完整写法。
Python3中:
super().__init__(参数1, 参数2 ···) 新增MRO,不需要写类名,并且会自动将self参数进行传递.
class School:
    school = 'xxx'

    def __init__(self, name, age, gender):
        self.name = name
        self.age = age
        self.gender = gender


class Student(School):

    def __init__(self, name, age, gender, courses):
        # 指定名称访问
        super().__init__(name, age, gender)
        # 课程
        self.courses = courses

    # 学生信息
    def stu_info(self):
        print('< %s >' % self.courses)


# 教师类
class Teacher(School):

    def __init__(self, name, age, gender, title):
        # 指定名称访问
        super().__init__(name, age, gender)
        # 教什么
        self.title = title

    # 老师的信息
    def Tea_info(self):
        print('< %s >' % self.title)


stu1 = Student('kid', 18, 'male', 'python')
tea1 = Teacher('xx', 30, 'male', 'python')
print(stu1.__dict__)
print(tea1.__dict__)
"""
{'name': 'kid', 'age': 18, 'gender': 'male', 'courses': 'python'}
{'name': 'xx', 'age': 30, 'gender': 'male', 'title': 'python'}
"""

2.查找顺序

# 查找顺序练习
class A:

    def aaa(self):
        print('from  - - A - - > aaa')

    def test(self):
        print('from  - - A - - >test')
        super().aaa()  # super 不会回头 往下 就直接到  B类中, 执行B.aaa() 打印  from  - - B - - > aaa 又回到这里
        print('AAA')

        def aaa(self):  # 上面的super() 目前是B  直接到B类去了 没造出来也没法调用,pycharm直接灰色显示
            print('from  - - test - - > aaa')


class B:
    def text(self):
        print('from - - B - - > test')

    def aaa(self):
        print('from  - - B - - > aaa')


class C(A, B):
    def aaa(self):
        print('from - - c - - > aaa')


obj = C()
print(C.mro())
obj.test()

"""
[<class '__main__.C'>, <class '__main__.A'>, <class '__main__.B'>, <class 'object'>]
from  - - A - - >test
from  - - B - - > aaa
AAA
"""

image-20211206231902645

3.组合

在一个类中引用另一个类最为对象的数据,称为类的组合.
解决类与类之间的代码冗余问题:
1.继承: 继承是一种什么是什么的关系,
2.组合: 组合是一组什么有什么的关系.
class A():
    def __init__(self, x):
        self.x = x

    def func1(self):
        return self.x


class B():
    def __init__(self, y):
        self.y = y


obj1 = A(10)
obj2 = B(obj1)


print(obj2.y)  # <__main__.A object at 0x000002520F3C9240>
print(obj2.y.x)  # 10
在类与类存在什么是什么关系的时候使用继承
在类与类存在什么有什么关系的时候使用组合
老师类和学生类继承人类
老师和学生就是人类 
# 人类
class People:
    def __init__(self, name, age, gender):
        self.name = name
        self.age = age
        self.gender = gender
        pass  # 其他属性


# 学生类
class Student(People):
    def __init__(self, name, age, gender):
        super().__init__(name, age, gender)


# 老师类
class Teacher(People):
    def __init__(self, name, age, gender):
        super().__init__(name, age, gender)
        pass  # 其他属性
        
现在添加需求:
给老师类和学生类添加课程.
课程包含 课程名称, 课程学习时间
# 人类
class People:
    def __init__(self, name, age, gender,  course_name, study_time):
        self.name = name
        self.age = age
        self.gender = gender
        self.course_name = course_name
        self.study_time = study_time


# 学生类
class Student(People):
    def __init__(self, name, age, gender, course_name, study_time):
        super().__init__(name, age, gender, course_name, study_time)



# 老师类
class Teacher(People):
    def __init__(self, name, age, gender, course_name, study_time):
        super().__init__(name, age, gender, course_name, study_time)
这个时候学校的来个门卫大爷,守护学校的安危.给他录信息.
# 人类
class People:
    def __init__(self, name, age, gender, course_name, study_time):
        self.name = name
        self.age = age
        self.gender = gender
        self.course_name = course_name
        self.study_time = study_time


# 学生类
class Student(People):
    def __init__(self, name, age, gender, course_name, study_time):
        super().__init__(name, age, gender, course_name, study_time)


# 老师类
class Teacher(People):
    def __init__(self, name, age, gender, course_name, study_time):
        super().__init__(name, age, gender, course_name, study_time)


# 守门大爷类
class Janitor_uncle(People):
    def __init__(self, name, age, gender, course_name, study_time):
        super().__init__(name, age, gender, course_name, study_time)
守门大爷要这不需要这个课程.
而人类中含有课程的属性也不合理.
将课程提出来新建一个课程类.
老师和学生有课程.
# 人类
class People:
    def __init__(self, name, age, gender):
        self.name = name
        self.age = age
        self.gender = gender


# 课程类
class Course():
    def __init__(self, course_name, study_time):
        self.course_name = course_name
        self.study_time = study_time


# 学生类
class Student(People):
    def __init__(self, name, age, gender):
        super().__init__(name, age, gender)


# 老师类
class Teacher(People):
    def __init__(self, name, age, gender):
        super().__init__(name, age, gender)


# 守门大爷类
class Janitor_uncle(People):
    def __init__(self, name, age, gender):
        super().__init__(name, age, gender)


# 造学生对象和老师对象
stu1 = Student('kid', 18, 'male')
tea1 = Teacher('qq', 30, 'male')
jan1 = Janitor_uncle('xx', 60, 'male')

# 造课程对象
subject = Course('Python', '48课时')

# 学学老师绑定课程信息
stu1.course = subject
tea1.course = subject

# 查看课程名称
print(stu1.course.course_name)  # Python
# 查看课程课时
print(stu1.course.study_time)  # 48课时

4.多态与多态性

程序中的多态:指在子类中覆写父类的方法.

类中使用多态的目的:
不是用来继承父类的属性和方法的,而是让父类来限制子类的行为.

同样的名称的方法在不同的子类中会有不同的的行为,但是它们有相同的特征,可是使用相同的方法来调用它们.

4.1抽象化

多态的本质是在不同的类中定义相同的方法,
然后在父类中限制子类必须有某个方法,实现某个功能.

抽象类就是从一堆类中抽取相似的功能创建一个类作为父类,子类继承父类,子类产生的对象在调用的时候,用法一样,方便使用。抽象类的定义的函数没有实现功能,只是规定了函数名,而且抽象类没法实例化。


被抽象的类无法实例化
抽象化的方法在子类中必须要有重名的方法.

Python不推崇这样类型.
import abc


# metaclass=abc.ABCMeta 抽象类
class Aniaml(metaclass=abc.ABCMeta):
    @abc.abstractmethod  # s抽象化方法
    def talk(self):
        pass  # 没有函数体直接pass


# 继承动物类,
class Cat(Aniaml):
    pass


cat = Cat()

"""
TypeError: Can't instantiate abstract class Cat with abstract methods talk
TypeError: 无法用抽象方法实例化抽象类 Cat 谈话
"""
import abc


# 抽象类
class Aniaml(metaclass=abc.ABCMeta):
    @abc.abstractmethod  # 抽象化方法
    def talk(self):
        pass  # 没有函数体直接pass


# 动物
class Animal:
    def talk(self):
        print('啊喔')


# 猫
class Cat(Animal):
    def talk(self):
        print('喵喵')


# 狗
class Dog(Animal):
    def talk(self):
        print('汪汪')


# 鸭子
class Duck(Animal):
    def talk(self):
        print('嘎嘎')


# 实例化对象
cat = Cat()
dog = Dog()
duck = Duck()

# 调用talk
cat.talk()
dog.talk()
duck.talk()

4.2鸭子类型

Python崇尚鸭子类型,如果看书起来像,叫起来也像,走路也像,那它就是鸭子.
将对象的使用方法统一,做一个接口,
调用这个接口函数,传入不同的参数,可以达到不同的功能.
封装一个函数,只要有它内部执行的这个方法即可。它不依赖继承关系,只要这样对象看起来像鸭子,走起来像鸭子就可以把它当作鸭子。
# 动物
class Animal:
    def talk(self):
        print('啊喔')


# 猫
class Cat(Animal):
    def talk(self):
        print('喵喵')


# 狗
class Dog(Animal):
    def talk(self):
        print('汪汪')


# 鸭子
class Duck(Animal):
    def talk(self):
        print('嘎嘎')


# 实例化对象
cat = Cat()
dog = Dog()
duck = Duck()

# 定义函数
def talk(obj):
    obj.talk()


# 调用
talk(cat)
talk(dog)
talk(duck)
不继承也没有约束 , 但是你自己要写
只要有相同的类型,那就是同一个类.
# 常用限制

class Animal():
	def speak(self):
		raise Exception('必须实现speak方法) 
	
class People(Animal):
	pass
class Pig():
	pass
class Dog():
	pass

def animal(animal):
	return animal.speak()
	
obj1 = People()
obj2 = Pig()
obj3 = Dog()

animal(obj1)
animal(obj2)
animal(obj3)

5.一切皆对象

Python中的一切皆对象,通过多态实现.
Python3中统一了类与类型的概念。
l = [1, 2, 3]   等同  l =  list(1, 2 ,3)
print(type(l))
<clsaa 'list'>
l1 .append(4)  --->   将l1传入append()   
对象调用方法将自己作为第一个参数传递。
list是类,类调用方法,方法绑定给类
l = [1, 2, 3]
list.append(l, 4)
print(l)  [1, 2, 3, 4]
print(isinstance(l1, list))  # True 判断某个值是否由某个类创建


class AAA():
    pass

aaa = AAA()

print(isinstance(aaa, AAA))  # True 判断某个值是否由某个类创建
Python中所有的数据都是通过调用类实例化得来,所以一切皆对象.

猜你喜欢

转载自blog.csdn.net/qq_46137324/article/details/121777851