进入python的世界_day27_python基础——对象动静态方法、继承、派生方法

一、动静态方法

​ 动态就是绑定给对象的方法直接在类体代码中编写即可,对象调用会自动将对象当做第一个参数

传入,类调用有几个形参就传几个实参;静态方法就是普通的函数

​ 意思就是动态会有人帮忙传一个参,静态就完全自己传啦

class Student:
    school_name = '摆烂大学'
    # 1.类中直接定义函数 默认绑定给对象 类调用有几个参数传几个 对象调用第一个参数就是对象自身
    def func1(self):
        print('看谁最能摆烂 真的好棒棒!!!')

    # 2.被@classmethod修饰的函数 默认绑定给类 类调用第一个参数就是类自身 对象也可以调用并且会自动将产生该对象的类当做第一个参数传入
    @classmethod
    def func2(cls):
        print('嘿嘿嘿 猜猜我是干嘛滴', cls)

    # 3.普普通通的函数 无论是类还是对象调用 都必须自己手动传参
    @staticmethod
    def func3(a):
        print('哈哈哈 猜猜我又是什么', a)


obj = Student()
# 1.绑定给对象的方法
obj.func1()
Student.func1(123)
Student.func1(Student)
# 其实就是必须得有个参数,也可以随便给
# 2.绑定给类的方法
Student.func2()  # fun2(Student)
obj.func2()  # func2(Student)
print(Student)

二、类的继承

1.介绍

​ 继承是指类与类之间名称空间的传递关系,如果一个类A可以全数访问另一个类B的所有名称,或者说类A拿到了类B所有属性的访问权限,那么就称类A继承了类B。

​ 我们可以通过子类访问到它继承的父类的所有属性

  • 被继承的类被称之为父类、基类、超类

  • 继承的类被称为子类、派生类

    ​ PS:一般用的比较多的就是父子类

'''单继承和多继承简单定义'''
class A:
    pass


class B:
    pass


class C(A):  # 单继承
    pass


print(C.__bases__)  # 查看自己的父类  (<class '__main__.A'>,)


class D(A, B):  # 多继承
    pass


print(D.__bases__)  # 查看自己的父类  (<class '__main__.A'>, <class '__main__.B'>)

三、继承的本质————节省代码

​ 对象:数据与功能的结合体

​ 类(子类):多个对象相同数据和功能的结合体

​ 父类:多个类(子类)相同数据和功能结合体

​ 抽象:把多个类公共的数据或功能那出来形成一个基类

​ 继承:从上往下获取每个基类中的资源 类与父类的本质都是为了节省代码

四、名字的查找顺序

​ 写在前头:不管哪种情况,都是先找自己名称空间的,再去找产生自己这个对象的类空间中的

1——不继承情况下名字的查找顺序

对象自身   >>>   产生对象的类    >>>   (如果还找不到,会报错)

2——单继承情况下名字的查找顺序

对象自身   >>>   产生对象的类     >>>    父类
# !!!注意 如果找到了self.啥啥的一定要留意,因为对象名被传进去后又要重新再找

3——多继承情况下名字的查找顺序

对象自身   >>>   产生对象的类     >>>    父类   >>>   父类的父类(如有)  都依据从左往右

一张图看懂:

  • 菱形继承查找问题:

    python会在MRO列表上从左到右开始查找基类,直到找到第一个匹配这个属性的类为止。 而这个MRO列表的构造是通过一个C3线性化算法来实现的。我们不去深究这个算法的数学原理,它实际上就是合并所有父类的MRO列表并遵循如下三条准则:
    
    1.子类会先于父类被检查
    2.多个父类会根据它们在列表中的顺序被检查
    3.如果对下一个类存在两个合法的选择,选择第一个父类
    

补充(了解):

​ 如果多继承是菱形继承,经典类与新式类的属性查找顺序不一样

​ 经典类:深度优先,会在检索第一条分支的时候就直接一条道走到黑

​ 新式类:广度优先,正常检索,直到最后才去找大脑

五、派生方法

super关键字

​ 可以让子类基于父类的某个方法拓展或是增加了一些条件、打上一些属性。

class OldboyPeople:
    school = 'OldBoy'

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

    def f1(self):
        print(f'{self.name} say hello')


class Student(OldboyPeople):
    def choose_course(self):
        print('学生%s 正在选课' % self.name)


class Teacher(OldboyPeople):
    #           老师的空对象,'egon',18,'male',3000,10
    def __init__(self, name, age, sex, salary, level):
        # 方式2:# 调用super()会得到一个特殊的对象,该对象会参照当前类的mro,去当前类的父类里找属性
        super().__init__(name, age, sex)  # 调用的是方法,自动传入对象
        self.salary = salary
        self.level = level

    def score(self):
        print('老师 %s 正在给学生打分' % self.name)


print(Teacher.mro())  # [<class '__main__.Teacher'>, <class '__main__.OldboyPeople'>, <class 'object'>]

派生用法

​ 能在继承状态下够修改父类的功能(不是修改父类,是改自己继承过来的)

​ 比如说列表、字典、字符串等常见方法操作可以加条件框定了

class MyList(list):
    def append(self, values):
        if values == 'jason':
            print('jason不能尾部追加')
            return
        super().append(values)

        
当我们想要做一些限制条件的时候也可以在类中添加。
obj = MyList()
print(obj, type(obj))
obj.append(111)
obj.append(222)
obj.append(333)
obj.append('jason')
print(obj)
posted @ 2022-11-06 22:37  yiwufish  阅读(322)  评论(0)    收藏  举报