面向对象微讲解(二)

面向对象微讲解(二)

动态方法

动态方法在面向对象有两种,分别是绑定给对象的方法和绑定给类的方法,我们分别来讲一下:

  1. 绑定给对象的方法
class Student:
    def run(self):
        print(self)

# 类调用绑定给对象的方法有几个参数就需要传几个参数
Student.run(123)  # 123
obj = Student()
# 对象调用绑定给对象的方法会自动将该对象当做第一个参数传入
obj.run()  # <__main__.Student object at 0x00000174396437B8>
  1. 绑定给类的方法
class Student:
    def run(self):
        print(self)
    @classmethod  # 类中创建绑定给类方法的语法糖
    def eat(cls):
        print(cls)

# 类调用绑定给类的方法会自动将该类当做第一个参数传入
print(Student)  # <class '__main__.Student'>
Student.eat()  # <class '__main__.Student'>
obj = Student()
# 对象调用绑定给类的方法也不需要传参,会自动将产生该对象的类当做第一个参数传入
obj.eat()  # <class '__main__.Student'>

静态方法

静态方法就是普普通通的函数,有几个参数就传入几个参数,不管是对象还是类来调用都是一样:

class Student:
    def run(self):
        print(self)
    @classmethod
    def eat(cls):
        print(cls)
    @staticmethod
    def sleep(a):
        print(a)

# 类调用静态方法有几个参数就传几个参数
Student.sleep(123)  # 123
obj = Student()
# 对象调用静态方法有几个参数就传几个参数
obj.sleep(321)  # 321

面向对象三大特征之继承

继承的含义及本质

	在讲面向对象的继承之前,我们先来讲讲继承的含义,或者说现实中继承的含义,现实生活中继承就是用来描述人与人之间财产
的从属关系,从根本上说,它是一种财产权利,但是又具有鲜明的身份特点,有什么鲜明的特点呢?比如儿子继承父亲,那么就可以拥有
父亲所有的财产。而面向对象中继承则是用来描述'类与类'之间'数据'的从属关系,所以呢类与类之间的关系就分为两种,一个是继承的,
也就是现实生活始中的儿子,我们叫做'子类'或者'派生类'。还有一种就是被继承的,就是现实生活始中的父亲,我们叫做'父类'或者'基类'。
    那么为什么要有继承呢?我们刚刚说面向对象中继承是用来描述类与类之间数据的从属关系,那就是说子类继承父类的数据之后,就可以
直接使用父类的数据,现实生活中也是,继承了父亲的财产之后你是有支配权的,也就是使用权,那么我们的子类也可以使用父类中的数据,
或者说方法,这样呢就大大减少了代码的冗余。我们来设想一下,我们定义了一个Person类,里面名字,年龄,性别,有这三种数据,然后
呢这时候又定义了一个Teacher类,里面也有名字,年龄,性别这三种数据,我们可以再写一遍,那如果有一百个呢,难道要写一百遍吗,所
以我们就要继承了,我们定义一个Person类之后,就相当于我们的父类,Teacher类就相当于子类,我们的子类就可以继承父类的数据,这样
就不用反复的写,减少了代码的冗余。
    有上述例子我们可以知道,子类继承了父类的数据,为什么继承父类的数据,就是为了减少代码的冗余,为什么要减少代码的冗余,就是
因为有很多相同的代码,所以呢我们就可以得出一个关于父类的结论:'多个类相同功能和数据的结合体就是父类'

继承的简单使用

我们刚刚已经讲过面向对象继承的含义,或者说本质,那要怎么使用呢?我们就用上述Person类与Teacher类来简单演示一下:

# 父类
class Person:
    def __init__(self,name,age,sex):
        self.name = name
        self.age = age
        self.sex = sex

# 子类,继承父类的方法就是在创建子类的时候在类名后面加括号,括号里的参数是父类的类名
class Teacher(Person):
    def teacher(self):
        print('%s是一个老师'% self.name)

obj = Teacher('oscar',21,'男')
obj.teacher()  # oscar是一个老师
# 我们还可以调用父类中的方法
print(obj.age)  # 21
'''
一个子类是可以继承多个父类的
'''

名字的查找顺序

  1. 不继承的情况
class Person:
    name = 'oscar'

obj = Person()  # 产生一个没有独有数据的对象
print(obj.name)  # oscar
print(Person.name)  # oscar
# 给对象添加独有数据
obj.name = 'jason'
print(obj.name)  # jason
print(Person.name)  # oscar
# 修改类中的数据
Person.name = 'tom'
print(obj.name)  # jason
print(Person.name)  # tom

在不继承其他类的情况下,先从对象自己的名称空间开始查找,如果没有就去产生该对象的类中查找。所以此种情况名字的查找顺序是:对象本
身 --> 产生对象的类

  1. 单继承的情况
class Person:
    name = 'jason'

class Teacher(Person):
    name = 'oscar'

obj = Teacher()  # 产生一个没有独有数据的对象
# print(obj.name)  # name = 'oscar'
# 我们把子类中的name注掉看看会怎样
# print(obj.name)  # jason
# 我们给对象添加一个独有name数据,再把注释都解掉看看会怎样
obj.name = 'tom'
print(obj.name)  # tom

在单继承的情况下,先从对象自己的名称空间开始查找,如果没有就去产生该对象的类中查找,还没有的话就去该类继承的父类中寻找,所以
此种情况名字的查找顺序是:对象本身 --> 产生对象的类 --> 该类继承的父类

  1. 多继承的情况

在讲多继承的情况下名字的查找顺序之前,我们先讲一个小知识点:

	我们的类呢是分为两种的,分别是经典类和新式类,在python2中存在经典类和新式类,python3中只有新式类,经典类与新式类
的区别关键就在于是否继承了一个默认的object类。
    新式类:直接或间接继承了object或者其子类的类。
    经典类:不继承任何类
class A:
    # name = 'A'
    pass
class B:
    name = 'B'
class C:
    name = 'C'
class Person(A,B,C):
    # name = '你好'
    pass
obj = Person()
print(obj.name)

在多继承的情况下,先从对象自己的名称空间开始查找,如果没有就去产生该对象的类中查找,还没有的话就去该类继承的父类中寻找,在
父类中查找的顺序是子类继承父类的顺序,也就是子类继承父类的时候括号里父类名字的顺序,从左往右,依次寻找,所以此种情况名字的
查找顺序是:对象本身 --> 产生对象的类 --> 该类继承的多个父类(顺序是从左往右)

多继承还有两种情况,我们简单了解一下:

1.非菱形继承
	非菱形继承就是子类继承的父类还有分类,也就是说子类继承了父类,父类呢又作为子类继承了其他的父类,那么这种情况就叫非
菱形继承,此种情况名字的查找顺序遵循'深度优先'。

它的执行结果依次就是:A --> B --> E --> C --> F --> D --> G

2.菱形继承
	非菱形继承就是子类继承的父类还有分类,也就是说子类继承了父类,父类呢又作为子类继承了其他的父类,最后呢又同时继承了
同一个类,那么这种情况就叫菱形继承,此种情况名字的查找顺序遵循'广度优先'。
它的执行结果依次就是:A --> B --> E --> C --> F --> D --> G --> M

派生类

派生类的本质还是子类。子类继承了父类之后,在父类的基础上增加一些数据或者功能的话,该子类就称为派生类,我们可以通过关键字super来实现。

class Person:
    def __init__(self,name,age,sex):
        self.name = name
        self.age = age
        self.sex = sex

class Teacher(Person):
    def __init__(self,name,age,sex,height,weight):
        # 用了Person类里面的__init__方法之后
        # super(Teacher, self).__init__(name,age,sex)  # 子类调用父类方法的完整语法
        super().__init__(name,age,sex)
        self.height = height  # 自己基于父类想要添加的数据或者功能
        self.weight = weight  # # 自己基于父类想要添加的数据或者功能

obj = Teacher('oscar',21,'男',185,60)
print(obj.__dict__)  # {'name': 'oscar', 'age': 21, 'sex': '男', 'height': 185, 'weight': 60}

这里是IT小白陆禄绯,欢迎各位大佬的指点!!!

posted @ 2022-04-07 17:49  陆禄绯  阅读(36)  评论(0)    收藏  举报