面向对象:继承、动静态方法
一、动静态方法
1 类中直接定义函数
类中直接定义函数(方法),则是默认将该函数绑定给类所产生的对象。类去调用该方法,需要几个参数就要传几个参数;而该类产生的对象去调用该方法,第一个self参数不用传,因为语法特性会自动把自己当作第一个参数self传进入。
2 被@classmethod修饰的函数
被@classmethod修饰的函数,默认绑定给类。类调用该函数,第一个参数cls,就是类自身的名字,按照语法特性会自动将类的名字传入使用;而该类所产生的对象也可以调用,并会自动将产生该对象的类的名字传进去使用。
3 静态函数 被@staticmethod修饰的函数
普通函数,没有特别语法。无论是类还是对象调用该函数,都必须自己手动传参。
class Student: # 1.类中直接定义函数,默认绑定给对象,类去调用方法 有几个参数就要传几个参数,对象去调用方法第一个self不用传 会自动把自己传进入 school_name = '武汉大学' def func1(self): print(f'{self}东湖游泳') # 2.被@classmethod修饰的函数,默认绑定给类,类调用第一个参数就类自身,对象也可以调用并会自动将产生该对象的类传进去 @classmethod def func2(cls): print('111', cls) # 3.静态函数 普通函数不自动传参 @staticmethod def func3(a): print('西湖游泳',a) obj = Student() # 1.绑定给对象的方法 obj.func1() # <__main__.Student object at 0x103097d60>东湖游泳 Student.func1(123) # 123东湖游泳 # 2.绑定给类的方法 Student.func2() # 111 <class '__main__.Student'> print(Student) # <class '__main__.Student'> "说明cls和类名 Student一致" obj.func2() # 111 <class '__main__.Student'> "对象可以调用func2,类也可以调用func2" # 3.静态方法 Student.func3('class') # 西湖游泳 class obj.func3(obj) # 西湖游泳 <__main__.Student object at 0x104dafd00>
二、面向对象-继承
1 面向对象三大特性
面向对象三大特性:封装、继承、多态
(1)三大特性中,继承是实操使用最多,最为核心
(2)封装和多态更概念化,较为抽象
2 继承的概念
1.继承的含义
在面向对象中,继承表示类与类之间资源的从属关系
eg:类A继承类B
2.继承的目的
在编程中,类A继承类B就是拥有了类B中所有的数据和方法使用权限
3 继承的实操
class Son(Father): pass # Son就继承了Father中所有的数据和方法
1.继承的语法
(1)在定义类的时候类名后面可以加括号填写其他类名,意味着继承其他类
(2)在python中支持多继承,括号内填写用逗号隔开
class Son(Father, Mother, Brother):
2.继承关系下类之间名称的叫法
(1)继承其他类的类 ,如:Son -- 我们称之为子类、派生类
(2)被继承的类,如:Father -- 我们称之为父类、基类、超类
4 继承的本质
1.继承的本质应该分为两部分:
(1)抽象:将多个类相同的东西抽出去形成一个新的类
(2)继承:将多个类继承抽取出来新的类
2.继承下的对象、子类、父类的本质
1 对象:数据与功能的结合体
2 类(子类):多个对象相同数据和功能的结合体
3 父类:多个类(子类)相同数据和功能的结合体
Ps:类与父类本质都是为了节省代码,为对象服务
5 名字的查找顺序
1.不继承情况下查找顺序
class C1: name = 'duoduo' def func(self): print('from func') # print(C1.name) # 类找名字看到在自己的名称空间 obj = C1() obj.name = '1111' # 由于对象原本没有name属性,该语法会在对象名称空间中创建一个name print(obj.__dict__) # {'name': '1111'} print(obj.name) # 1111 print(C1.name) # duoduo """ 在不继承的情况下: 对象查找名字的顺序 1。先从自己的名称空间中查找 2。自己没有再去产生该对象的类中查找 3。如果类中也没有,那么直接报错 对象自身名称空间 --》》类名称空间
2.不继承情况下查找顺序
对象点名字,永远要先从对象自身开始一步步查找
以后看到self点名字,一定要先知道谁是self
class F1: name = 'duoduo' def func(self): print('from func') class S1(F1): name = 'kevin' obj = S1() obj.name = 'oscar' print(obj.name) """ 对象自身>>> 产生对象的类>>>父类 """
***小练习题
class A1: def func1(self): print('from A1 func1') def func2(self): print('from A1 func2') self.func1() class B1(A1): def func1(self): print('from B1 func1') self.func2() obj = B1() obj.func1()
3.多继承情况下名字的查找顺序
(1)非菱形继承
# 1 非菱形继承:深度度优先,从左往右每条道走完为止 class F1: name = 'F1' class F2: name = 'F2' class F3: name = 'F3' class S1(F1, F2, F3): # name = 'hahaha' pass obj = S1() # obj.name = '全局' print(obj.name) """ 对象自身>>> 产生对象的类>>> 父类(从左到右依次) """
(2)菱形继承
# 2菱形继承:广度优先,最后在找深度 class G: name = 'from G' pass class A(G): # name = 'from A' pass class B(G): name = 'from B' pass class C(G): 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 pbj = S1() print(pbj.name) # mro方法,可以直接列出名字的查找顺序 print(S1.mro())

图片:继承的查找顺序
(3)mro方法
可以直接列出名字的查找顺序
# mro方法,可以直接列出名字的查找顺序 print(S1.mro()) ---------------------- [<class '__main__.S1'>, <class '__main__.D'>, <class '__main__.A'>, <class '__main__.E'>, <class '__main__.B'>, <class '__main__.F'>, <class '__main__.C'>, <class '__main__.G'>, <class 'object'>]
6 经典类与新式类
经典类:不继承object或者其子类的类
新式类:继承object或者其子类的类
在python2中有经典类和新式类
在python3中只有新式类
class Student(object):pass ps:以后我们在定义类的时候 如果没有其他明确的父类 也要习惯写object兼容python 2.x 版本
7 派生方法super
定义:子类基于父类某个方法做了扩展
子类可以派生出自己新的属性,在进行属性查找的时候,子类中的属性名会优先于父类被查找。
1. 方法一:直接调用
如果想要让子类派生出的方法在父类的方法上叠加,可以直接调用
# 父类 class School: def __init__(self, name, age, gender): self.name = name self.age = age self.gender = gender # 子类 Student class Student(School): def __init__(self, name, age, gender, sid): # 子类直接调用父类的方法,由于调用的是函数,需要填写self参数 School.__init__(self, name, age, gender) self.sid = sid def choice_course(self): print(f'{self.name}正在选课')
2.super()
方法
调用super()
会得到一个特殊的对象,该对象专门用来引用父类的属性
# 完整语法 super(自己的类名, self).想要调用的父类的方法(形参) # 在形参中无需填写self参数,会自动传入对象的名字
举例:
# 父类 class School: def __init__(self, name, age, gender): self.name = name self.age = age self.gender = gender # 子类 Student class Student(School): def __init__(self, name, age, gender, sid): # super() 子类调用父类的方法 super(School, self).__init__(name, age, gender) self.sid = sid def choice_course(self): print(f'{self.name}正在选课') # 子类 Teacher class Teacher(School): def __init__(self, name, age, gender, level): super().__init__(name, age, gender) self.level = level def teach_course(self): print(f'{self.name}上课')
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· Blazor Hybrid适配到HarmonyOS系统
· Obsidian + DeepSeek:免费 AI 助力你的知识管理,让你的笔记飞起来!
· 解决跨域问题的这6种方案,真香!
· 一套基于 Material Design 规范实现的 Blazor 和 Razor 通用组件库
· 数据并发安全校验处理工具类