Python面向对象三大特征

面向对象的三大特征:封装继承多态

一、封装

  • 广义的封装:函数的定义和类的定义
  • 狭义的封装:一个类中的某些属性,如果不希望被外界直接访问,则可以将该属性私有化,该属性只能在当前类中被直接访问;如果在类的外面需要访问(即获取或修改),则可以通过暴露给外界的函数间接访问
  • 封装的本质:将类中的属性进行私有化

1.1 私有属性

以实例属性为例,类属性一样,私有化只要在类属性前面添加两个下划线_

  • 公有属性

    正常使用self.变量 = 值定义,可以在类的外面直接用对象进行访问到

# 定义类
class Person1():
    def __init__(self, name, age):
        # 公开属性
        self.name = name
        self.age = age

# 创建对象
p1 = Person1("张三", 10)
# 通过对象可以直接访问
print(p1.name, p1.age)
  • 私有属性

    在定义属性的时候,在前面添加两个下划线_,如上诉的name修改为__name

    • 注意
    • 此时变量名为__name,而不是原来的name
    • 进行限制属性动态绑定的时候,也要书写__xxx形式
    • 当前类中的函数中,可以通过 self.__xxxx访问
    • 类的外面直接用对象无法访问
# b.私有属性/属性的私有化
class Person2():
    # 注意事项:哪怕是定义了私有属性,进行了限制属性动态绑定的时候,也要书写__xxx形式
    __slots__ = ("__name", "__age")

    def __init__(self, name, age):
        # 私有属性,只需要在属性名的前面添加两个下划线__
        self.__name = name
        self.__age = age

    # 注意3:在当前类中的函数中,可以self.__xxx访问的
    def show(self):
        print(f"姓名:{self.__name},年龄:{self.__age}")

# 创建对象,通过对象可以直接访问
p2 = Person2("张三", 10)
# 通过对象无法直接访问
# print(p2.__name, p2.__age)  # 报错:AttributeError: 'Person2' object has no attribute 'name'
p2.show()

1.2 私有函数

既然属性可以私有,那么函数也可以私有

函数私有化方式和属性私有化类似,只要在函数名前面添加两个下划线_

class Person3:
    # 创建公有函数
    def func1(self):
        print("func1函数~~~")

    # 创建私有函数
    def __func2(self):
        print("__func2私有函数~~~")

# 创建对象
p3 = Person3()
# 通过对象调用函数
p3.func1()
# p3.__func2()  # AttributeError: 'Person3' object has no attribute '__func2'

此时,私有函数无法再类外通过对象进行调用,如果访问,则会报错

如果要访问私有函数,可以在共有函数中调用私有函数

class Person3:
    # 创建公有函数
    def func1(self):
        print("func1函数~~~")

        # 调用私有函数
        self.__func2()

    # 创建私有函数
    def __func2(self):
        print("__func2私有函数~~~")

# 创建对象
p3 = Person3()
# 通过对象调用函数
p3.func1()

输出结果

func1函数~~~
__func2私有函数~~~

1.3 类比总计

解释下面不同形式的变量出现在类中的意义

a:普通属性,也被称为公开属性,在类的外面可以直接访问

_a:在类的外面可以直接访问,但是不建议使用,容易和私有属性混淆

__a:私有属性,只能在类的内部被直接访问。类的外面可以通过暴露给外界的函数访问

__a__:在类的外面可以直接访问,但是不建议使用,因为系统属性和魔术方法都是这种形式的命名

​ 如:__slots____init____new____del____name____add____sub____mul__

综上所述:公有属性使用a,私有属性使用__a,系统属性使用__a__

二、继承

  • 如果两个或者两个以上的类具有相同的属性和方法,我们可以抽取一个类出来,在抽取出来的类中声明各个类公共的部分。其中:

​ 被抽取出来的类——父类(father class)或着超类(super class)或者基类(base class)

​ 两个或两个以上的类——子类或者派生类

​ 他们之间的关系——子类继承自父类;或者父类派生了子类

  • 简单来说

​ 一个子类只有一个父类,被称为单继承

​ 一个子类有多个父类,被称为多继承

  • 语法:
# 单继承
class 子类类名(父类类名):
    类体
# 多继承
class 子类类名(父类类名1,父类类名2.......):
    类体

注意:object是Python中所有类的根类

  • 继承的好处

​ 简化代码

​ 复用性

​ 可读性

2.1 单继承

一个子类只有一个父类,被称为单继承

父类

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

    def eat(self):
        print("eating~~~~~~")

子类1:子类中没有定义__init__,创建子类对象,自动调用父类中的__init__

class Doctor(Person):
    pass

doc = Doctor("王大夫", 45)
print(doc.name, doc.age)
doc.eat()

子类2:如果子类中定义了__init__,且定义了特有的属性,则在子类的__init__中调用父类的__init__

有三种方式可以调用

  • 方式一
super(当前类,self).__init__(参数列表)
  • 方式二
super().__init__(参数列表)
  • 方式三
父类.__init__(self,参数列表)
# b.如果子类中定义了__init__,且定义了特有的属性,则在子类的__init__中调用父类的__init__
class Student(Person):
    def __init__(self, name, age, score):
        # 方式一:super(当前类,self).__init__(参数列表)
        # super(Student, self).__init__(name, age)

        # 方式二:super().__init__(参数列表)
        # super().__init__(name, age)
        # 方式三:父类.__init__(self,参数列表)
        Person.__init__(self, name, age)
        self.score = score

    def study(self):
        print("studying~~~~~~~")

stu = Student("小明", 10, 88)
print(stu.score)
print(stu.name, stu.age)
stu.eat()
stu.study()

2.2 多继承

一个子类有多个父类,被称为多继承

如果在子类的__init__中调用父类的__init__,方式如上,建议使用方式三,目标明确

# 多继承,一个子类有多个父类
# 父类1
class Flyable():
    def fly(self):
        print("飞行")

# 父类2
class Runable():
    def run(self):
        print("行走")

# 子类
class Bird(Flyable, Runable):
    pass

# 创建子类对象
bird = Bird()
# 调用父类1的方法
bird.fly()
# 调用父类2的方法
bird.run()

三、多态

继承是多态的前提

  • 体现形式:

    • 一种事物的多种体现形式,举例:动物有很多种
    class Animal:
      pass
    
    class Cat(Animal):
      pass
    
    class SmallCat(Cat):
      pass
    
    # isinstance(对象,类型) :判断对象是否是制定的类型
    sc = SmallCat()   # sc 是多态的体现形式
    print(isinstance(sc, SmallCat))  # True
    print(isinstance(sc, Cat))  # True
    print(isinstance(sc, Animal))  # True
    print(isinstance(sc, object))  # True
    • 定义时并不确定是什么类型,要调用的是哪个方法,只有运行的时候才能确定调用的是哪个
    class Animal:
      def style(self):
          print("walking~~~~~")
    
    class Cat(Animal):
      pass
    
    class Dog(Animal):
      pass
    
    class Fish(Animal):
      def style(self):
          print("swimming~~~~~")
    
    class Bird(Animal):
      def style(self):
          print("flying~~~~~")
    
    def show(ani):  # ani 就是多态的体现形式
      ani.style()
    
    d = Dog()
    c = Cat()
    f = Fish()
    b = Bird()
    
    show(d)
    show(c)
    show(f)
    show(b)

    输出结果

    walking~~~~~
    walking~~~~~
    swimming~~~~~
    flying~~~~~
THE END
喜欢就支持一下吧
点赞14 分享
评论 抢沙发
头像
欢迎您留下宝贵的见解!
提交
头像

昵称

取消
昵称表情代码图片

    暂无评论内容