ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

Python学习day25-面向对象之组合,多态和封装

2019-08-28 20:01:04  阅读:264  来源: 互联网

标签:md cm Python 多态 day25 rgb 0px margin color


 

<style></style>

Python学习day25-面向对象之组合,多态和封装组合多态与多态性封装

Python学习day25-面向对象之组合,多态和封装

组合

组合,简单来说就是对象的某个属性是另一个类的对象,有点类似于嵌套的意思,但是不全一样。使用组合最大的优点还是可以减少代码的冗余。举一个最简单的组合的例子:

     
xxxxxxxxxx
8         1
class Foo:
2
    def __init__(self,bar):
3
        self.bar = bar
4
class Bar:
5
    pass
6
f = Foo()
7
f.bar = Bar()
8
f = Foo(Bar())
   

上述例子中,类中的Foo的内置属性中就有Bar类,所以是组合的一种体现。

再来看一个稍微复杂一点的例子:

需求,我们需要一个老师类,一个学生类,学生类包括姓名,年龄,所选课程,

老师类包括姓名,年龄,所教课程。

运用组合的方法实现如下:

     
xxxxxxxxxx
59         1
# 定义一个人基类,老师类和学生类都从此继承出来
2
class Person:
3
school = 'oldboy'
4
5
def __init__(self, name, age):
6
self.name = name
7
self.age = age
8
9
# 定义老师类,包括姓名,年龄,所教课程
10
class Teacher(Person):
11
def __init__(self, name, age, course):
12
super().__init__(name, age)
13
self.course_list = course
14
# course是课程对象,是老师教授的课程
15
# 定义课程对象,课程包括名字,价格,时间周期
16
class Course:
17
def __init__(self, c_name, c_price, c_period):
18
self.name = c_name
19
self.price = c_price
20
self.period = c_period
21
# 定义学生类,继承于人基类,且和课程类有所组合
22
class Student(Person):
23
# course = list()#课程的列表不能放在这里,因为每次实例化都会清零,所以这是错误放法
24
25
def __init__(self, name, age):
26
super().__init__(name, age)
27
self.course_list = list()# 课程列表应该放在这里,也就是实例化时候默认加载的地方,init里面
28
29
# course是课程对象,是学生选择的课程
30
def choose_course(self, course):
31
# self.course = list()#课程同样不能放在这里,因为每次学生调用选课方法的话课程列表就会清零,错误放法
32
self.course_list.append(course)
33
        
34
# 定义一个学生查看自己所选课程的方法
35
def tell_all_course(self):
36
# 循环学生选课列表,每次拿出一个课程对象
37
for course in self.course_list:
38
print(course.name)
39
40
# 实例化产生一个课程对象
41
course = Course('Python', 20180, 7)
42
# 实例化产生一个学生对象
43
stu1 = Student('nick', 19)
44
# 学生对象调用选课方法,选择上面产生的课程对象
45
stu1.choose_course(course)
46
47
48
stu2 = Student('www', 19)
49
stu2.choose_course(course)
50
stu2.choose_course(Course('linux', 19999, 5))
51
stu2.tell_all_course()
52
53
# print(stu1.__dict__)
54
# print(stu2.__dict__)
55
56
# teacher = Teacher('tank', 19, '高级', course)
57
# 查看老师教授的课程名
58
# print(teacher.course.name)
59
# 这种连续调用的方法会极大的减少代码量,也会使整个的项目变得简练,逻辑清楚,即每个对象都是一个百宝箱。
   

 

多态与多态性

多态,顾名思义,多种形态,即一类事物的多种形态。

比如现实生活中,动物类,包括猪,狗,猫,长颈鹿,老虎等等,就是同一类事物的多重形态,当然我们还可以继续往下分类,这个问题在这里不是关键。

而多态性就是指在不考虑实例类型的情况下使用实例。

我们用最简单的实例来实现一下多态的概念。

     
xxxxxxxxxx
31         1
class Animal:
2
def speak(self):
3
pass
4
5
6
class Pig(Animal):
7
def speak(self):
8
print('哼哼哼')
9
10
11
class Dog(Animal):
12
def speak(self):
13
print('汪')
14
15
16
class People(Animal):
17
def speak(self):
18
print('hello')
19
20
21
pig = Pig()
22
dog = Dog()
23
people = People()
24
pig.speak()
25
dog.speak()
26
people.speak()
27
def animal_speak(obj):
28
obj.speak()
29
animal_speak(pig)
30
31
# 这个实例的意思大概就是,每个动物都能发出自己的声音,那么我们给每个动物定义一个类,以及同样的speak方法,那么我们就可以通过定义另外一个调用自身speak方法的函数来实现动物发出声音这个功能,只需要在animal_speak后面加上需要发声的动物就行了。
   

所以其实这种调用方式有一个问题,就是如果定义别的动物类的时候其内部没有speak这个方法,那么就会报错,所以我们就要想办法去约束这个事情,官方的话就是我们要约束子类的共有特性。

常用的约束方法有两种:

  1. 一个是用abc实现接口的统一化,abc和装饰器的用法有些类似,需要在前面加@

         
    xxxxxxxxxx
    1 37         1
    import abc
    2
    class Animal(metaclass=abc.ABCMeta):
    3
    @abc.abstractclassmethod
    4
    def speak(self):  # 规定了我的子类必须有这个方法,如果没有,调用就没有输出,就不能利用多态性,做约束作用
    5
    pass
    6
    7
    8
    class Pig(Animal):
    9
    @abc.abstractclassmethod
    10
    def speak(self):
    11
    print('哼哼哼')
    12
    13
    14
    class Dog(Animal):
    15
    @abc.abstractclassmethod
    16
    def zz(self):
    17
    print('汪')
    18
    19
    20
    class People(Animal):
    21
    @abc.abstractclassmethod
    22
    def cc(self):
    23
    print('hello')
    24
    25
    26
    pig = Pig()
    27
    dog = Dog()
    28
    people = People()
    29
    pig.speak()
    30
    dog.speak()
    31
    people.speak()
    32
    33
    34
    def animal_speak(obj):
    35
    obj.speak()
    36
    37
    38
    animal_speak(pig)
       

     

  2. 第二个就是比较常用的方式,就是用异常处理来约束子类

         
    xxxxxxxxxx
    1 11 1 19         1
    class Animal():
    2
    def speak(self):
    3
    # 主动抛出异常
    4
    raise Exception('需要重写')
    5
    6
    7
    class Pig(Animal):
    8
    def speak(self):
    9
    print('哼哼哼')
    10
    11
    12
    pig = Pig()
    13
    14
    15
    def animal_speak(obj):
    16
    obj.speak()
    17
    18
    19
    animal_speak(pig)
    20
    # 这种情况下,如果子类里面没有父类的方法,那么调用时候就会主动抛出异常,通知你需要重写这些方法。
       
    • 说起来是有这两种约束子类的方法,但实际上,Python是一种十分崇尚鸭子类型的语言,鸭子类型就是说,只要你走起路来像鸭子,那么你就是鸭子。换做在Python里就是说,只要你能实现这些功能,我们不太关心你是怎么实现的,用了什么方法或者变量,所以一般Python做的一些比较大的项目,并不会去约束你的子类方法是如何写的,而只是靠程序员自己来把控,自由度非常高。

封装

封装的字面意思就是把一堆东西放在袋子里,然后封上口。但是如果封装==隐藏的话,就太片面了。

封装只是在于明确其使用范围,封装的属性或者方法,都可以在类内部直接使用,但是不能被外部直接使用,我们需要另外写一些函数或者方法,来让外部以我们想让他们看到的方式看到这些隐藏的内容。

我们先来看一下如何去把类里面的属性或方法设置成隐藏:

     
xxxxxxxxxx
1 18         1
# 隐藏属性:主要目的是为了保护原有数据,不让别人修改
2
# 把name隐藏起来
3
class Person:
4
def __init__(self, name, age):
5
self.__name = name# 在需要隐藏的属性前面加上__就可以将其设置成隐藏属性,也就是封装
6
self.age = age
7
8
def get_name(self):  # 可以另外增加一些功能,或者不同的打印方式
9
return self.__name
10
11
12
p = Person('nick', 18)
13
14
print(p.age)
15
# print(p.__name)
16
print(p.get_name())
17
# Python中隐藏的属性就真的访问不到了么,并不是的
18
# 实际上隐藏的属性还是可以访问到
19
print(p.__dict__)# 我们先查看对象的字典属性,里面会写真正的被隐藏变量的名字
20
print(p._Person__name)# 直接用我们看到的异常属性名字就可以直接看到隐藏变量
21
# 不过非常不推荐这种做法,毕竟隐藏属性就是为了隐藏起来,你非要去把人家调出来干嘛。。。
         
xxxxxxxxxx
1 14     1
# 隐藏方法:主要目的是隔离复杂度,使用者不用考虑有多少种方法,只需要调用那个对外的方法就可以了,毕竟里面的方法你也看不到
2
class Person:
3
def __init__(self, name, age):
4
self.__name = name
5
self.age = age
6
7
def __speak(self):  # 通过封装方法,让方法只在内部使用,对外只提供一个接口就可以
8
print('666')
9
10
11
p = Person('nick', 89)
12
# p._Person__speak()
13
print(Person.__dict__)
    14
   

 

标签:md,cm,Python,多态,day25,rgb,0px,margin,color
来源: https://www.cnblogs.com/Xu-PR/p/11426159.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有