面向对象之继承
面向对象之继承
动静态绑定方法
1.绑定给对象的方法 self
class Student:
school_name = '动态绑定'
def func1(self):
print('绑定给对象')
obj = Student()
Student.func1(123)
obj.func1()
'我们在类中定义的函数 如果用类来调用 有几个参数就传几个参数 '
"用对象来调用第一个参数 self 默认就是对象本身"
====================================================================================
2. 绑定给类的方法 cls
@classmethod
def func2(cls):
print('绑定给类')
Student.func2()
obj.func2()
给类绑定 必须使用 @classmethod 可以看成语法糖装饰器,此时调用就会将 """调用的类 当做第一个参数,对象来调用就会将 产生对象的类 当做第一个参 """
====================================================================================
3. 静态方法 无论谁来调用都必须传参 类似于函数
@staticmethod
def func3(a):
print('根据形参个个数给我传参')
Student.func3(1)
obj.func3(2)
使用 @staticmethod ,形参有多少个就得传多少个"无论类还是对象"
继承的概念
面向对象有3大特征.
- 封装 2.继承 3. 多态
"继承是其中最为重要 核心的。"
封装和动态略微抽象
继承的含义
继承的含义就类似与现实生活中,不想继续奋斗,回去继承家业。 在编程中就表示子类继承父类的资源(数据,或功能)。
继承的目的
子类拥有父类的数据与功能使用权
继承实操
定义类的时候类名后面的括号可以填写其他类名.意味着继承其他类
此时的 其他类 就是 "父类"别称:基类,超类
自身类 就是 "子类"别称: 派生类
代码实操:
class Father():
money = '我是你爸爸,我有1000W人民币'
class Son(Father):
pass
"作为儿子我不想奋斗了,直接拿爸爸的钱"
obj = Son()
print(obj.money) # 我是你爸爸,我有1000W人民币
可以继承多个父类
class Father():
money1 = '我是你爸爸,我有1000W人民币'
pass
class Grandpa():
money2 = '我是你爷爷, 我有1个亿'
class Mom():
money3 = '儿子,我摊牌了,我是万亿神豪'
class Son(Father,Grandpa,Mom):
pass
"作为儿子我不想奋斗了,直接拿爸爸的钱"
obj = Son()
print(obj.money1,obj.money2,obj.money3)
# 我是你爸爸,我有1000W人民币 |我是你爷爷, 我有1个亿| 儿子,我摊牌了,我是万亿神豪
继承的本质
对象: 数据与功能的结合体
类: 含有多个对象相同的数据与功能的结合体
"父类: 多个子类相同的数据与功能的结合体"
说了这么多其实为什么有这些东西出现,就是节省我们的代码量,重复的代码可以继承
本质分为两部分:
抽象: 将多个类相同的数据或功能抽出去形成一个新的类
继承: 将多个类 抽取的相同的东西 继承成新的类
名称的查找顺序
"不继承" 名字的查找顺序:
class A1:
name = '我是A1的名字'
def func(self):
print('我是func 的')
obj = A1()
print(obj.name) # 我是A1的名字
"此时查找的名字是从类里找到的"
obj.name = '我是对象自身的'
print(obj.name) # 我是对象自身的
"""此时因为我们使用对象.name的方式在对象自身不存该名字的情况下就新建键值对所以对象内部含有了一个name名字 此时的查找到名字就变成了对象内的名字"""
print(A1.name) # 我是A1的名字
"因我们使用类名.name 的方式查找名字 找到的是类里面的 name"
所以得出结论:
不继承情况下查找名字的顺序是
对象内 ---- 产生对象的类
====================================================================================
继承的情况下:
class A1:
name = '我是A1的名字'
class B1(A1):
# name = '我是B1的'
pass
obj = B1()
print(obj.name) # 我是A1的名字
"""对象是B1的类产生的,所以会先从 对象内部查找此名字 没找到| 接着去B1也没找到 |
此时B1继承了A1 接着去A1找,找到了 """
得出结论:
对象自身 - 产生对象的类 - 产生对象的类继承的父类
====================================================================================
多继承的情况下:
class A1:
# name = '我是A1的名字'
pass
class B1():
# name = '我是B1的'
pass
class C1():
name = 'C1'
class D1(A1,B1,C1):
# name = 'D1'
pass
obj = D1()
print(obj.name) # C1
"如上 按继承 顺序 从左往右开始找"
====================================================================================
非菱形继承:
class A:
# name = 'from A'
pass
class B:
# name = 'from B'
pass
class C:
# name = 'from C'
pass
class D(A):
# name = 'from D'
pass
class E(B):
# name = 'from E'
pass
class F(C):
# name = 'from F'
pass
class S1(D, E, F):
pass
obj = S1()
print(obj.name) # DA EB FC
非菱形继承 遵循 深度优先
"走完一个分支与其父类,再走另外一个分支与其父类,按照S1继承的父类 从左往右的顺序"
====================================================================================
总结:
综上所述我们在所有情况下都是按照 "对象 --- 产生对象的类 --- 父类" 的顺序查找名称
====================================================================================
知识点:
菱形继承的情况下
父类中名字的查找顺序就是按照继承时从左往右依次查找
如果多个父类还有分类 那么遵循"广度优先"
DA EB FC ABC的父类 G
经典类与新式类
其实就是 继承没继承 object
经典类: 不继承 所有类
新式类: 直接或者间接继承了object或者其子类的类
python2 中 有经典类与新式类
python3 中只有新式类"所有类默认都继承 object"
"为了我们编写的代码兼容性更强我们以后无论在哪个版本中 最好也都写上object"
class A1(object):
pass
派生方法
打个比方,比如我们人类 中的学校里有
可以分成:
学生, 老师, 学生和老师都是人。
学生属性有: 姓名,年龄,爱好,学号
老师属性也有: 姓名,年龄,爱好,等级
"""姓名,年龄,爱好这些都是作为人的共有属性。学号和等级都是学生和老师拥有的特有属性那么我们代码就可以不用反复的写这些共有属性,把他们全部放到人类的属性中去,后期可以用老师和学生来继承这些属性。"""
代码实现:
class Person:
def __init__(self, name, age, hobby):
self.name = name
self.age = age
self.hobby = hobby
'人类的共有属性'
class Teacher(Person): # 继承 Person 的init
def __init__(self, name, age, hobby, level):
super().__init__(name, age, hobby) # 使用super 使用 Person的属性
self.level = level # 老师独有的属性
class Student(Person):
def __init__(self, name, age, hobby, sid):
super().__init__(name, age, hobby)
self.sid = sid # 学生独有的属性
stu1 = Student('tank','14','read',123333322) # 传数据
print(stu1.__init__)
print(stu1.name) # tank
print(stu1.sid) # 123333322
stu2 = Teacher('jason','28','rap','高级教师')
print(stu2.__init__)
print(stu2.name) # jason
print(stu2.level) # 高级教师
这样我们就可以即使用共同属性,也可以调出 独有属性。
必须使用关键字 super "子类调用父类的方法"
====================================================================================
列表派生方法:
class Mylist(list):
def append(self,values):
if values == 123:
print('123不可以添加,滚')
return
super().append(values)
obj = Mylist()
obj.append(1)
obj.append(12)
obj.append(123)
print(obj)
"""append是列表的内置方法,我们这里可以直接把类变成列表,产生一个对象并使用列表的append方法 往里添加数据,并设置过滤条件 。 此时def append(self,values):接收的参数第一个就是对象本身,第二个就是(1)"""