面向对象(二)


内容概要

  • 动态方法与静态方法
  • 面向对象的三大特征之:继承
  • 继承的本质
  • 名字的查找顺序
  • 派生类
  • 派生功能之重写列表

动态方法与静态方法

动态方法

# 动态方法
	1.绑定给对象的方法
  	class Student:
      def run(self):
        prtin(self)
 
  	# 类调用绑定给对象的方法:有几个参数就需要传几个参数
    Student.run(123)  # 123
    # 对象调用绑定给对象的方法:会自动将对象当做第一个参数传入
    obj1 = Student()  # 创建空对象
    obj1.run()  # <__main__.Student object at 0x000001B03BCFD400>
  
  2.绑定给类的方法
  	class Student:
      @classmethod   # 动态方法
      def eat(cls):  # 自动生成cls 即calss缩写 没有其他含义只是名字
        prtin(cls)
        
  	# 类调用绑定给类的方法:会自动将类当做第一个参数传入
    print(Student)  # 
    Student.eat()  # 
    # 对象调用绑定给类的方法:也不需要传参 会讲产生该对象的类自动当做第一个参数传入
    obj1 = Student()  # 创建空对象
    obj1.eat()  # 
    

静态方法

# 静态方法
    class Student:
        @staticmethod  # 静态方法
        def speak(cls):
            print(cls)
            
    1.普普通通的函数:无论谁来调 都必须传固定的参数个数
    # 类调用静态方法:要自己传值
    Student.speak(123) # 123
    # 对象调用静态方法:要自己传值
    obj1 = Student()  # 创建空对象
    obj1.speak(321)  # 321
    

面向对象的三大特征之:继承

    '''
    面向对象的三大特征:
        继承 封装 多态
    其中最重要的就是继承!!!
    '''
    # 继承的含义
    在现实生活中继承就是用来描述人与人之间资源的从属关系
        eg:儿子继承父亲的资产 遗嘱等 那么儿子就会拥有之前父亲拥有的一切
    '面向对象中继承使用则是用于描述类与类之间的从属关系'
        eg:类A继承类B 那么类A就可以使用类B中所有的数据(数据、功能...)

    # 继承的目的
    现实生活中可以通过继承的方式快速的积累财富 少奋斗n多年 而且可多继承
        eg:有多个爹 磅多个富婆
    '面向对象中通过继承可以减少代码冗余 提升开发效率 同样也支持多继承'
        eg:类A可以继承多个类同时拥有多个类里面的代码使用权

    # 继承的基本使用
        """
        class B:
            print('from B')
        class A(B):  
            pass
        *我们将被继承的类称为:父类或者基类       B
        *继承别人的类称为:子类或者派生类	      A
        """
      在python中一个类可以同时继承多个父类
        class A(B,C,D):
          pass

继承的本质

    抽象:由下往上抽取相同特征
    继承:由上往下直接白嫖资源
    """
    在面向对象编程中 其实类和父类的主要功能都是用来减少代码冗余的

    对象:数据与功能的结合体
    类:多个对象相同数据和功能的结合体
    父类:多个类相同数据和功能的结合体
    """
    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')

查找顺序

不继承和单继承查找

'''名字的查找顺序永远都是 先从当前对象自身开始查找'''

# 不继承的情况下
	名字的查找顺序是
  	先从对象自己的名称空间中查找 没有则去类里面的名称空间查找
    	对象	>>>	类
  '''注意设置值的情况下是在自身的名称空间中添加或者修改数据'''
  
# 单继承的情况下
	名字的查找顺序是
  	先从对象自己的名称空间中查找 没有择取产生对象的类中查找
    如果还没有并且类有父类则去父类中查找 以此往复下去!!!
    	对象	>>>	类	>>> 父类
  经典案例
  	class A:
      def f1(self):
          print('from A.f1')
      def f2(self):
          print('from A.f2')
          self.f1()  '''以后看到self点东西 一定要问自己self是谁'''
    class MyClass(A):
       def f1(self):
            print('from MyClass.f1')
    obj = MyClass()
    obj.f2()
    # 执行的方法分别是A里面的f2和MyClass里面的f1

多继承情况查找

    # 多继承的情况下(了解)
	"""
	在python2中存在经典类与新式类
	在python3中只有新式类
		区分的关键在于是否继承了一个默认的object类
			新式类:直接或者间接继承了object或者其子类的类
			经典类:不继承任何的类
	"""
    class A:
      pass
    # print A.__bases__  # 空的
    # print(A.__bases__)  # (,)
    """
    有时候我们在定义类的时候会习惯性的写
    class MyClass(object):
        pass
    为了兼容python2和python3
    """
    
      强度:研究菱形和非菱形问题object不参与图形构建
  非菱形继承的情况下
  	父类中名字的查找顺序就是按照继承时从左往右依次查找
   	如果多个父类还有分类 那么遵循"深度优先"
  		ADBECF
  菱形继承的情况下
  	父类中名字的查找顺序就是按照继承时从左往右依次查找
   	如果多个父类还有分类 那么遵循"广度优先"
  		ADBECFG
非菱形
class D:
    name = 'from D'
    pass
class E:
    name = 'from E'
class F:
    name = 'from F'

class A(D):
    name = 'from A'
    pass
class B(E):
    name = 'from B'
class C(F):
    name = 'from C'

class Myclass(A,B,C):
    # name = 'from MyClass'
    pass

obj = Myclass()
print(obj.name)

菱形
class G:
    name = 'from G'

class D(G):
    name = 'from D'
    pass
class E(G):
    name = 'from E'
class F(G):
    name = 'from F'

class A(D):
    name = 'from A'
    pass
class B(E):
    name = 'from B'
class C(F):
    name = 'from C'

class Myclass(A,B,C):
    # name = 'from MyClass'
    pass

obj = Myclass()
print(obj.name)

派生类

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

class Teacher(Person):
    def __init__(self,name,age,gender,level,salary):
        # 用了Person类里面的__init__方法之后
        # super(Teacher,self).__init__(name,age,gender)  # 子类调用父类的方法 完整语法
        super().__init__(name,age,gender)  # super 子类调用父类的方法 精简语法
        # 自己还要添加一个额外的东西
        self.level = level
        self.salary = salary

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
"""
如果自己写的子类需要使用父类的方法 并且还需要基于该方法做扩展
这样的子类我们称之为派生类(本质还是子类)      
    那么可以使用super关键字来实现
"""
t1 = Teacher('jason',18,'male','满级',3.1)
s1 = Student('kevin',28,'female',20220407,2)
print(t1.__dict__)  # {'name': 'jason', 'age': 18, 'gender': 'male', 'level': '满级', 'salary': 3.1}
print(s1.__dict__)  # 'name': 'kevin', 'age': 28, 'gender': 'female', 'stu_id': 20220407, 'class_id': 2}

重写列表

class MyClass(list):
    def append(self,args):
        if args == 123:
            print('数字123不能追加')
            return
        super(MyClass, self).append(args)
obj1 = MyClass()
obj1.append(333)
obj1.append(222)
obj1.append(123)
print(obj1)  # 数字123不能追加  [333, 222]