面向对象编程:动静态方法、类的继承、派生类
2022.4.7类相关方法及操作
- 动态方法与静态方法
- 面向对象的三大特性之一:继承
- 继承的名字查找顺序
- 派生类
一、动态方法与静态方法
1、动态方法
(1)绑定给对象的方法
复制代码
- 1
- 2
- 3
- 4
- 5
- 6
- 7
class Student:
def run(self):
print(self)
Student.run(123) # 类调用绑定给对象的方法:有几个参数就需要传几个参数
obj = Student()
obj.run() # 对象调用绑定给对象的方法:会自动将对象当作第一个参数传入
(2)绑定给类的方法
复制代码
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
class Student:
# 定义类方法关键字
def eat(cls): # 参数一般写cls,约定俗成
print(cls)
# 类调用绑定给类的方法:会自动将类当做第一个参数传入
print(Student) # <class '__main__.Student'>
Student.eat() # <class '__main__.Student'>)
# 对象调用绑定给类的方法:也不需要传参,会将产生该对象的类自动当做第一个参数传入,其实就是把外层类名传入内层类参数,相当于外层类是内层类的父类,然后通过对象调用内外层类
obj1.eat() # <class '__main__.Student'>
2、静态方法
复制代码
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
class Student:
# 定义静态方法关键字
def speak(a):
print(a)
静态方法:即普通的函数,定义之后就不会自动传self,但是括号内有几个参数就必须传几个参数
# 类调用静态方法:要自己传值
Student.speak(123)
# 对象调用静态方法:也要自己传值
obj1.speak(321)
二、面向对象的三大特征之一:继承
1、继承的含义
继承,顾名思义,承接别人的东西或者上一代的资源,比如儿子和父亲
面向对象中的继承:即用来描述类与类之间数据的从属关系
ps:类A继承类B,那么类A就可以使用类B中所有的数据(数据、功能...)
2、继承的目的
减少代码冗余,提升开发效率,继承同样支持多继承,即继承多个类
3、继承的基本使用
复制代码
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
class A(B):
...
# 我们将被继承的类称:父类
# 继承其他类的类称:子类或派生类
class A(B,C,D):
...
# python中一个类可以同时继承多个父类
4、继承的本质
个人理解:被继承的类其实就是继承者类和其他类的相同特征抽取出来的,即多个子类,有父类的共同特征
简单来说,就是:
抽象:由下往上抽取相同特征(定义父类时)
继承:由上往下直接白嫖资源(子类继承父类时)
复制代码
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
"""
在面向对象编程中 其实类和父类的主要功能都是用来减少代码冗余的
对象:数据与功能的结合体
类:多个对象相同数据和功能的结合体
父类:多个类相同数据和功能的结合体
"""
class Person: # 定义一个父类,也有子类的相同特征
def __init__(self, name, age, gender):
self.name = name
self.age = age
self.gender = gender
class Teacher(Person): # 定义一个子类
def teach(self):
print(f'{self.name}老师正在讲课')
class Student(Person): # 定义一个子类
def study(self):
print(f'{self.name}学生正在学习')
stu1 = Student('jason', 18, 'male') # 生成对象,并向父类传值
三、继承的名字查找顺序
1、不继承的情况下
先从对象自己的名称空间中查找,没有则去类中的名称空间查找
对象>>>类
注意:使用对象修改或添加值只能修改对象本身,不能修改类中值
复制代码
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
class A:
a = 'from A'
obj = A() # 生成对象obj,此时obj相当于一个空字典
a = 'from obj'
obj.append(a) # 对象中添加数据
print(obj.a) # 'from obj'
obj.pop(a) # 删除对象数据a
print(obj.a) # 'from A'
2、单继承的情况下
先从对象自己的名称空间查找,没有再从类中查找,没有的话,若有父类,再从父类中查找
对象>>>类>>>父类
复制代码
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
class A:
def f1(self):
print('from A.f1')
def f2(self):
print('from A.f2')
self.f1() # 相当于obj.f1(),看到self.东西 一定要问自己self是谁
class MyClass(A):
def f1(self):
print('from MyClass.f1')
obj = MyClass()
obj.f2() # 执行的方法分别是A里面的f2和MyClass里面的f1
3、多继承的情况下
多继承的情况下python2与python3有所不同:
复制代码
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
"""
在python2中存在经典类与新式类
在python3中只有新式类
区分的关键在于是否继承了一个默认的object类
新式类:直接或者间接继承了object或者其子类的类
经典类:不继承任何的类
"""
class A: # python2环境
pass
class B: # python3环境
pass
print A.__bases__ # 空的
print(B.__bases__) # (<class 'object'>,)
因此,python3中时默认继承了一个object类,如果要写的时候同时兼容python2和python3,可以一律加上(object)
class MyClass(object):
pass
注意:研究菱形和非菱形问题object不参与图形构建,下面会介绍菱形和非菱形继承
(1)继承多个类情况下
,名字查找顺序是从左往右的,即:
复制代码
- 1
- 2
class A(B,C,D): # 默认先找类B,然后是A,最后是D
...
那么什么是非菱形继承和菱形继承呢
(2)非菱形继承
复制代码
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
非菱形继承的情况下
父类中名字的查找顺序就是按照继承时从左往右依次查找
如果多个父类还有分类 那么遵循"深度优先"
class C:
pass
class E:
pass
class B(C):
pass
class D(E):
pass
class A(B,D):
pass
此情况查找顺序如下图
(3)菱形继承
复制代码
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
菱形继承的情况下
父类中名字的查找顺序就是按照继承时从左往右依次查找
如果多个父类还有分类 那么遵循"广度优先"
class F:
pass
class C(F):
pass
class E(F):
pass
class B(C):
pass
class D(E):
pass
class A(B,D):
pass
此情况查找顺序如下图
永恒真理:名字查找顺序永远是从当前对象自身开始查找
四、派生类
概念:如果自己写的子类需要使用父类的方法 并且还需要基于该方法做扩展
这样的子类我们称之为派生类(本质还是子类)
那么可以使用super关键字来实现
复制代码
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
首先定义父类和子类
class Person:
def __init__(self,name,age,gender):
self.name = name
self.age = age
self.gender = gender
子类:teacher
class Teacher(Person):
def __init__(self,name,age,gender,level,salary):
# 用了Person类里面的__init__方法之后,如何创建自己的特有属性呢
两种写法:
1.super(Teacher,self).__init__(name,age,gender) # 子类调用父类的方法 完整语法
2.super().__init__(name,age,gender) # 子类调用父类的方法 精简语法
# 自己还要添加一个额外的东西
self.level = level
self.salary = salary
子类:student
class Student(Person):
def __init__(self,name,age,gender,stu_id,class_id):
# 用了Person类里面的__init__方法之后
super().__init__(name, age, gender)
# 自己还要添加一个额外的东西
self.stu_id = stu_id
self.class_id = class_id
t1 = Teacher('jason',18,'male','满级',3.1) # 使用父类方法
s1 = Student('kevin',28,'female',1302010201,2)
print(t1.__dict__)
print(s1.__dict__)
五、函数和方法的区别
复制代码
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
from types import MethodType,FunctionType
class Foo:
def test(self):
print('绑定给对象的方法,对象来调用是方法,类来调用是函数')
def test2(cls):
print('绑定给类的方法,类来调用是方法,对象来调用是方法')
def test3():
print('静态方法,类来调用是函数,对象来调用是函数')
# 类来调用静态方法:静态方法就是函数
print(isinstance(Foo.test3,MethodType)) # False
print(isinstance(Foo.test3,FunctionType)) # True
# 类调用类的绑定方法
print(isinstance(Foo.test2,MethodType)) # True
print(isinstance(Foo.test2,FunctionType)) # False
# 类调用对象的绑定方法
print(isinstance(Foo.test,MethodType)) # False
print(isinstance(Foo.test,FunctionType)) # True
#对象调用对象的绑定方法
foo=Foo()
print(isinstance(foo.test,MethodType)) # True
print(isinstance(foo.test,FunctionType)) # False
# 对象调用类的绑定方法
print(isinstance(foo.test2,MethodType)) # True
print(isinstance(foo.test2,FunctionType)) # False
# 对象调用静态方法
print(isinstance(foo.test3,MethodType)) # False
print(isinstance(foo.test3,FunctionType)) # True
# 函数,有几个值就要传几个值
# 方法,可以自动传值,对象的绑定方法,类的绑定方法
派生功能前瞻
复制代码
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
class MyClass(list): # 可直接继承内置方法
def append(self,args): # 自己定义一个append方法
if args == 123: # 判断条件后执行后面代码
print('数字123不能追加')
return
super(MyClass, self).append(args) # 筛选条件后添加传进来的args
obj1 = MyClass() # 生成对象obj
obj1.append(333) # 走super方法,添加数据到obj
obj1.append(222) # 走super方法,添加数据到obj
obj1.append(123) # 走if判断,直接退出
print(obj1) # {333,222}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步