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'}
"""
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()
print('AAA')
def aaa(self):
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
"""
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)
print(obj2.y.x)
在类与类存在什么是什么关系的时候使用继承
在类与类存在什么有什么关系的时候使用组合
老师类和学生类继承人类
老师和学生就是人类
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)
print(stu1.course.study_time)
4.多态与多态性
程序中的多态:指在子类中覆写父类的方法.
类中使用多态的目的:
不是用来继承父类的属性和方法的,而是让父类来限制子类的行为.
同样的名称的方法在不同的子类中会有不同的的行为,但是它们有相同的特征,可是使用相同的方法来调用它们.
4.1抽象化
多态的本质是在不同的类中定义相同的方法,
然后在父类中限制子类必须有某个方法,实现某个功能.
抽象类就是从一堆类中抽取相似的功能创建一个类作为父类,子类继承父类,子类产生的对象在调用的时候,用法一样,方便使用。抽象类的定义的函数没有实现功能,只是规定了函数名,而且抽象类没法实例化。
被抽象的类无法实例化
抽象化的方法在子类中必须要有重名的方法.
Python不推崇这样类型.
import abc
class Aniaml(metaclass=abc.ABCMeta):
@abc.abstractmethod
def talk(self):
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
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()
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中所有的数据都是通过调用类实例化得来,所以一切皆对象.