面向对象编程:动静态方法、类的继承、派生类

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: @classmethod # 定义类方法关键字 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: @staticmethod # 定义静态方法关键字 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 此情况查找顺序如下图

LScfi9.png

(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 此情况查找顺序如下图

LS21nf.md.png

永恒真理:名字查找顺序永远是从当前对象自身开始查找

四、派生类

概念:如果自己写的子类需要使用父类的方法 并且还需要基于该方法做扩展
这样的子类我们称之为派生类(本质还是子类)
那么可以使用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('绑定给对象的方法,对象来调用是方法,类来调用是函数') @classmethod def test2(cls): print('绑定给类的方法,类来调用是方法,对象来调用是方法') @staticmethod 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}
posted @   马氵寿  阅读(109)  评论(0编辑  收藏  举报
点击右上角即可分享
微信分享提示
评论
收藏
关注
推荐
深色
回顶
展开