Python-面向对象之封装与多态

组合

什么是组合

组合指的是 一个对象中的属性是另一个对象的引用

  • 组合是对象与对象的关系,一种什么有什么的关系,一个对象拥有另一个对象
  • 继承是类与类的关系,一种什么是什么的关系,子类与父类是从属关系

使用组合的目的

和继承一样减少代码冗余

如何使用组合

上代码

# 组合练习

# 定义相同属性的属性
class People:
    def __init__(self,name,age,sex):
        self.name = name
        self.age = age
        self.sex = sex

    # 每个对象都都选课的权利/功能,添加课程功能,添加的课程利用组合知识点,添加课程的对象,
    # 进而对 课程对象操作
    def add_course(self,course_name):
        self.course_list.append(course_name)

    # 打印当前对象中所有课程的信息
    def tell_all_course(self):

        # 拿到当前对象的课程列表,列表中存放的是一个个课程对象
        for course_obj in self.course_list:

            # 每一个课程对象可以调用它的绑定方法查看课程的信息,
            # 利用for循环遍历 进而可以查看所有课程
            course_obj.tell_info()


class Teacher(People):
    def __init__(self,name,age,sex):
        super().__init__(name,age,sex)
        self.course_list = []

class Student(People):
    def __init__(self,name,age,sex):
        super().__init__(name,age,sex)
        self.course_list = []

# 定义课程类
class Course:
    def __init__(self,name,period,price):
        self.name = name
        self.period = period
        self.price = price

    def tell_info(self):
        print(f"""
        课程名称:{self.name}
        课程周期:{self.period}
        课程价钱:{self.price}
        """)

# 实例化老师和学生类
tea1 = Teacher("tank",18,"man")
stu1 = Student("qinyj",20,"man")

# 实例化课程类
python = Course("python","6个月","20K")
linux = Course("linux","6个月","15K")

# 使用组合将课程对象添加到老师属性里面
tea1.add_course(python)
tea1.add_course(linux)

# 对对象的属性进行调用,循环遍历出所有课程
tea1.tell_all_course()

封装

什么是封装

封装值得就是把一堆属性(特征和技能)封装到一个对象中

存数据不是目的,取才是目的,创建出对象后可以"."的方式获取属性

为什么要封装

封装的目的是为了方便存取,可以通过对象“.”的方式获取属性

如何封装

定义类:

​ 特征:变量--》数据属性

​ 技能:函数--》方法属性

在类内部,定义一堆属性(特征和技能)

通过对象.属性 得到/修改属性值

访问限制机制

什么是访问限制机制

在类内部定义,凡是以__开头的数据属性与方法属性都会被python类隐藏起来,让外部不能直接访问这些属性,比如:__name = "qinyj"

访问限制机制的目的

一堆隐私属性不能被外部轻易访问的属性可以隐藏起来,不能被外部直接访问

好处:对重要数据获取的逻辑更加严谨,保证数据的安全

接口:隐私属性可以通过封装一个接口,在接口内部做业务逻辑的处理,把数据返回给调用者。

注意:python中不会强制限制属性的访问,类内部__开头的属性,只是做了一种变形,若想直接访问,调用变形后的名字即可。即:

class Foo:
    __name = "qinyj" 	--》变形为 _类名__属性名

print(Foo._Foo__name)

如何使用访问限制

上代码

class Teacher:
    def __init__(self,name,age,sex):
        self.__name = name
        self.__age = age
        self.__sex = sex

    def get_info(self):
        # 验证用户逻辑
        user = input("请输入用户")
        pwd = input("请输入密码")
        if user == "qinyj" and pwd == "123":
            print(f"""
            姓名:{self.__name}
            年龄:{self.__age}
            性别:{self.__sex}
            """)

    def set_info(self,name,age,sex):

        # 验证输入逻辑
        if not isinstance(name,str):
            raise TypeError("名字必须要使用字符串")
        if not isinstance(age,int):
            raise TypeError("年龄必须要使用数字")
        if not isinstance(sex,str):
            raise TypeError("性别必须要使用字符串")

        self.__name = name
        self.__age = age
        self.__sex = sex

t = Teacher("qinyj",18,"man")
# t.get_info()

t.set_info("jack",18,"man")
t.get_info()

property

什么是property

property是python内部的装饰器,主要是给类内部的方法使用的。

将类内部的方法变成属性引用

为什么要用property

在对象调用某个方法时,将类内部的方法看成一个普通的数据属性调用

如何使用property

@property

上代码

'''
计算人体的bim值
bim值 = 体重 / (身高 * 身高)
'''
class People:
    def __init__(self,name,weight,height):
        self.name = name
        self.weight = weight
        self.height = height

    @property		
    def bim(self):
        return self.weight / (self.height * self.height)

    # 了解
    @property
    def get_name(self):
        return self.name

    @get_name.setter
    def set_name(self,value):
        self.name = value

    @get_name.deleter
    def del_name(self):
        del self.name

p = People("qinyj",120,1.72)
print(p.bim)		# bim方法不用加括号 自动触发执行bim方法

print(p.get_name)
p.set_name = "jack"	# 自动触发set_name方法
print(p.get_name)
del p.del_name		# 自动触发del_name方法
print(p.get_name)

多态与多态性

什么是多态

多态指的是同一种事物的多种形态

多态的目的

  • 多态也称之为多态性,在程序中继承就是多态的表现形式
  • 父类:定义一套统一的标准
  • 子类:遵循父类统一的标准

多态的最终目的:为了让多种不同类型的对象,在使用相同功能情况下,调用同一名字的方法名,统一子类编写的规范,为了让使用者更方便调用相同功能的方法

如何实现多态性

  • 继承父类
  • 继承抽象类
  • 鸭子类型

注意,在python中不会强制要求子类必须遵循父类的一套标准,所以出现了抽象类

上代码

# 多态性骚操作
class Cat:
    def talk(self):
        print("say miao")

# 定义一个普通函数,将对象放入函数参数调用类内部的方法
def func(animal):
    animal.talk()

cat1 = Cat()    # 实例化出一只猫的对象
func(cat1)


# 多态:同一种事物的多种形态
# 多态性:一种调用方式,不同的执行结果

抽象类

什么是抽象类

即abc模块(abcstract_class)

使用抽象类的目的

强制子类必须遵循父类的一套标准

如何使用

import abc

上代码

import abc

class Animal(metaclass=abc.ABCMeta):

    # 使用此装饰器就意味着统一了方法,子类若继承此类,方法名必须遵循此类的规范定义
    # 同时不能少方法
    # 可以派生出自己的属性和方法
    # 使用的时候在此类()内添加 metaclass=abc.ABCMeta
    # 想让什么方法遵循就在什么方法上加 @abc.abstractmethod
    @abc.abstractmethod
    def eat(self):
        pass

    @abc.abstractmethod
    def drink(self):
        pass


class Pig(Animal):

    def eat(self):
        print("猪在吃饭")

    def drink(self):
        print("猪在喝水")

    def run(self):
        print("猪在跑步")

p = Pig()

鸭子类型

什么是鸭子类型

在不知道当前对象时何物的时候,但是你长得像鸭子,那么你就是鸭子类型

在python中,不推荐使用抽象类强制限制子类的定义,但是推荐类都遵循燕子类型

使用继承:耦合性太高,程序可扩展性差

鸭子类型:耦合性低,程序可扩展性高

即不使用继承,又按照某一种规范编写程序

小结

1.组合:
		- 什么是组合
				组合指的是一个对象中的属性,是另一个对象.
		- 为什么要使用组合
   			组合目的和继承一样, 为了减少代码冗余.
2.封装:
		- 什么是封装?
				封装指的是把一堆属性(特征与技能)封装到一个对象中.
				存数据的目的是为了取, 对象可以"."的方式获取属性.
				
		- 为什么要封装?
        封装的目的为了方便存取,可以通过对象.属性的方式获取属性.

3.访问限制机制:
    - 什么是访问限制机制?
         在类内部定义, 凡是以__开头的数据属性与方法属性,都会被python内部隐藏起来,让外部不能"直接"访问类内部的__开头的属性.

    - 访问限制机制的目的?
        一堆隐私的属性与不能被外部轻易访问的属性, 可以隐藏起来,不被外部直接调用.   
   
4.property:
    - 什么是property
        python内置的装饰器, 主要是给类内部的方法使用.

    - 为什么要用property
        在对象调用某个方法时,将对象.方法()变成对象.方法(看起来想一个普通的数据属性)
        obj.bmi() == obj.bmi

    - 如何使用property
        @property
        def 类内部的方法(self):

5.多态:
    - 什么是多态?
        多态指的是同一种事物的多种形态.

    - 多态的目的:
        多态的目的是为了, 让多种不同类型的对象, 在使用相同功能的情况下,调用同一个名字的方法名.
        父类: 定义一套统一的标准.
        子类: 遵循父类统一的标准.
        
    - 如何实现:
        - 继承父类
        - 继承抽象类
        - 鸭子类型

6.抽象类的目的:
		强制子类必须遵循父类的一套标准.

7.鸭子类型:
    - 什么是鸭子类型?
        在不知道当前对象是何物的情况下,但是你长得像鸭子,那么你就是鸭子类型.
    - 继承:
        耦合性太高,程序的可扩展性差

    - 鸭子类型:
        耦合度低,程序的可扩展性强
posted @ 2019-10-11 17:14  GeminiMp  阅读(201)  评论(0编辑  收藏  举报