python面向对象[基础]

222 阅读6分钟

1.类成员

1.类变量
  • 类的成员变量描述对象的属性值根据对象不同会产生区别,此时类变量称为实例变量
  • 类变量的成员变量描述对象的属性值根据对象的不同不会产生区别,称此类变量为类变量
  • 类变量是归属类的,实例变量是归属对象的
  • 类变量书写在类定义的里面,实例变量书写在__init__方法中
class Dog:
    var = "都是狗"  #类变量 定义在类里
    # 所以的对象都有这个变量值
    def __init__(self, name, age):  # 对象变量 定义在init里
        self.name = name
        self.age = age
# 类名.变量名 方式访问类变量
# 类名.变量名 = 变量值  方式修改
类变量名的访问

1.类名.类变量名(推荐)

2.对象名.类变量名

类变量名的修改

类名.类变量名 = 变量值

不允许使用 对象名.类变量名 = 变量名修改 这样会给该变声明一个独有属性 仅修改该对象的属性值

类变量可以私有化

作用:记录创建了多少个对象 +=1

记录一个总数 每个方法都能调用 且通用

2.类方法

定义格式:

在类方法中,类属性访问可以通过 cls.类属性名 来访问

class 类名:
    @classmethod
    def 方法名(cls, 形参):
        方法体

调用格式:

类名.方法名(实参) (推荐) 对象名.方法名(实参) (不推荐)

如果类方法和成员方法名字冲突时,不能使用 对象名.方法名(实参) 调用方法,这样会调用写在后面的方法,

通过cls(变量名)可以创建一个对象

只要方法名称相同(无论修饰符是否一样) 就会出现覆盖的情况 后面写的会被调用

注意:类方法和成员方法之间的相互调用

类方法中不允许使用实例变量和实例方法

实例方法中允许使用类变量和类方法,推荐使用类名调用

class Dog:
    var = "都是狗"  #类变量 定义在类里
    def __init__(self, name, age):  # 对象变量 定义在init里
        self.name = name
        self.age = age
    @classmethod   # 定义一个类方法
    def show_me(cls):
        print("类方法的狗子") 
        # slef.show    成员方法无法调用类方法和类变量

    def show(self):  # 定义一个成员方法
        print(Dog.var) # 类方法可以定义成员变量
        Dog.show_me()  #类方法可以调用成员方法
        print("成员方法的狗子")
dog1 = Dog("狗子", 18)
dog1.var = "不是狗"
print(dog1.var)
dog1.show()
  • 注意:self 和cls的自动补充:

    ​ 这只是一个变量名而已,自动补充的 可以用任何变量名代替

  • 静态方法(了解 不常用)
    @staticmethod  # 静态方法的创建
    def show1():
        print("一个静态方法")
    

    调用方法:

    类名.方法名(实参) (推荐)

    对象名.方法名(实参) (不推荐)

    静态方法的定义与类无关,与对象无关,可以转化成函数定义

    用途:用于存放工具类,使其存放在一起,类名.即可看到

3.面向对象名称的总结

  • 公有变量:类中 有self.前缀的变量都是公有变量
  • 全局变量:在文件的最外层,或者在函数中加了global的变量
  • 局部变量:定义在函数中的,类中的方法里,成员变量名没有self的也是局部变量
  • 独有变量:只有这一个对象才有的变量,
  • 私有变量:类变量名前有2个下划线__的称为私有变量,只能在类的内部使用
  • 类变量:定义在类的下边,没有在方法里面
  • 成员变量 = 公有变量
  • ______init__方法:构造方法
  • 对象 可以称为实例

5.2继承

1.基础格式:

​ class 子类名称(父类名称):

​ pass

继承描述的是一种类间关系,一个类从另一个类获取成员信息的类间关系。

继承作用:继承父类的变量和方法;子类可以添加父类没有的东西,父类私有成员不可以被继承

2.继承的关系结构图

  • object是所有类的父类

查看继承关系结构:类名.mro

class Anmail:
    pass
class Cat(Anmail):  #Anmail是cat的父类
    pass
class SmallCat(Cat):  # Cat是smallcat的父类
    pass
print(SmallCat.__mro__)
# 此时输出:(<class '__main__.SmallCat'>, <class '__main__.Cat'>, <class '__main__.Anmail'>, <class 'object'>)
# 即  object是Anmail的父类,Anmail是Cat的父类,Cat是SmallCat的父类

3.重写

子类重写了__init__时,实例化子类,就不会调用父类已经定义的__init__,即被重写

  • 在子类中可以定义与父类相同名称的方法,此时子类的方法对父类的方法构成了重写。 如果子类重写了父类的方法,使用子类对象调用被重写的方法时,执行子类中重写后的方法

__str__方法就是一个重写

调用父类被重写的方法:

​ 1 父类名.init(self,参数)#注意名字是父类

​ 2 super(子类名,self).init(参数)#注意名字是子类,而且init后是se1f之外的参数

​ 调用格式一:父类名.方法名(对象)

​ 调用格式二:super(本类名,对象).方法名()

​ 调用格式三:super().方法名() (推荐)

重写后 父类和子类的信息都会有 而不是覆盖

class People:
    def __init__(self, age):
        self.name = None
        self.age = age
    def said(self):
        print("父类说")
class Man(People):
    def __init__(self):
        super().__init__(None)  # 子类重写时如何调用父类的成员变量? 参数不能写变量吗?
        self.sex = "man"
    def said(self):
        print("子类说")
        super().said()
people1 = People(18)
print(people1.age)
man1 = Man()
print(man1.age)

init方法中,子类要重新父类init时,父类传递了参数,子类也需要传参

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

class Teacher(Person):
    def __init__(self,name,age): 父类有
        super().__init__(name,age)
        self.id = "111"

4.多继承

格式: class 子类名(父类名1,父类名2,父类名3):

​ pass

如果方法,变量有冲突,则先选择写在前面的父类

重写:父类名.方法名(self)

​ 如果写super().方法名(),则默认调用写在前面的父类名方法(父类名1)

需要查看具体重写的那个方法 同样用:类名.___ __mro _

5.多态

同一个对象,在不同的使用环境中以不同的形态展示其功能,称该对象具有多态特征

​ 多态发生在继承关系的基础之上

# 同一个对象,在不同的使用环境中以不同的形态展示其功能,称该对象具有多态特征。
class Eat:
    def breakfast(self):
        print("吃饭")
class Sleep:
    def bed(self):
        print("睡觉")
class Man(Eat,Sleep):
    def breakfast(self):
        print("吃早饭呢")
    def bed(self):
        print("在床上睡觉")
class Demo:
    def test(self,who):
        who.breakfast()
eat1 = Eat()
man1 =Man()  # 以多态的形式展现出来 需要eat  但是给了一个具有eat方法的子对象也行
demo1 = Demo()
demo1.test(man1)
鸭子类型

对象在语法层面满足调用关系,实际不具有对应的对象形态,称该对象此时具备鸭子类型

鸭子类型是一种特殊的多态表现形式 鸭子类型和多态就差了一个继承

class Eat:
    def rice(self):
        print("吃米饭")
class Paly:
    def player(self):
        print("玩游戏")
class Man(Eat,Paly):  # 子类
    def rice(self):
        print("吃好吃的米饭")
    def player(self):
        print("玩好玩的游戏")
class Stdent:  # 没有关系的类
    def rice(self):
        print("学生也不吃饭")
    def play(self):
        print("好学生不玩游戏")
class Demo:
    def demo1(self,who):
        who.rice()
demo = Demo()
man =Man()
std1 = Stdent()
demo.demo1(man)  # 继承
demo.demo1(std1) # 鸭子类型(没有继承)