Python学习(十三)—— 面向对象程序设计

Posted jennifer224

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Python学习(十三)—— 面向对象程序设计相关的知识,希望对你有一定的参考价值。

三大编程范式

1、面向过程编程

2、函数式编程

3、面向对象编程

编程进化论

1、编程最初是无组织无结构的,由简单控制流中按步写指令

2、从上述的指令中提取重复的代码块或逻辑,组织到一起(比如定义了一个函数),便实现了代码重用,且代码由无结构走向结构化,创建程序的过程变得更加具有逻辑性。

3、我们定义函数都是独立于函数外定义变量,然后作为参数传递给函数,这意味着:数据与动作是分离的

4、如果我们把数据和动作内嵌到一个结构(函数或类)里面,那么我们就有了一个“对象系统”(对象就是数据与函数整合到一起的产物)

 

技术图片
 1 #学校类
 2 #特征:name,addr,type
 3 #动作:考试,招生,招聘老师,开除学生
 4 
 5 def school(name,addr,type):
 6     def init(name,addr,type): #定义初始化类:属性和动作
 7         sch= {
 8             "name":name,
 9             "address":addr,
10             "type":type,
11             "exam":exam,
12              "hire":hire
13         }
14         return sch
15 
16     def exam(school):
17         print("%s学校在考试" % school["name"])
18 
19     def hire(school):
20         print("%s%s学校在招聘老师" % (school["name"], school["type"]))
21 
22     return init(name,addr,type) #在这一步调用init函数
23 
24 s1 = school("东华","北京东路","私立")
25 print(s1)
26 #{‘name‘: ‘东华‘, ‘address‘: ‘北京东路‘, ‘type‘: ‘私立‘, ‘exam‘: <function school.<locals>.exam at 0x0000024FDF0C9488>, ‘hire‘: <function school.<locals>.hire at 0x0000024FDF0C9510>}
27 print(s1["name"])
28 # 东华
29 s1["exam"](s1)
30 # 东华学校在考试
31 s1["hire"](s1)
32 # 东华私立学校在招聘老师
33 s2 = school("清华", "海淀区", "公立")
34 s2["hire"](s2)
35 # 清华公立学校在招聘老师
用函数实现面向对象的程序设计

 

面向对象设计与面向对象编程

面向对象设计(Object-oriented design):将一类具体事物的数据和动作整合到一起,即面向对象设计

面向对象设计(OOD)不会特别要求面向对象编程语言。事实上,OOD可以由纯结构化语言来实现(如C),但如果想要构造具备对象性质和特点的数据类型,就必须在程序上作更多努力。

面向对象编程(Object-oriented programming):用定义类+实例/对象的方式去实现面向对象的设计

类和对象

类:把一类事物的相同的特征和动作整合到一起就是类

对象:是基于类而创建的一个具体的事物(具体存在的),也是特征和动作整合到一起

类与对象的关系:对象都是由类产生的。

什么是实例化:由类生产对象的过程叫实例化,类实例化的结果就是一个对象,或者说是一个实例。

初识类

在python中声明类和声明函数极其相似

 

 1 """
 2 class 类名: #类的首字母大写
 3     "类的文档字符串"
 4     类体
 5 """
 6 #创建一个类
 7 class Data:
 8     pass
 9 
10 #用类Data实例化一个对象d1
11 d1 = Data()

注意:在Python2中需要区分经典类和新式类,在Python3中无论如何定义,都是新式类

1 #经典类
2 class Data:
3     pass
4 #新式类
5 class New_data(object): #object是父类
6     pass

属性

类是用来描述一类事物,类的对象指的是这一类事物中的一个个体

凡是事物就有属性,属性分为:

1、数据属性:即变量

2、函数属性:即函数,在面向对象里通常称为方法

注意:类和对象均用点来访问自己的属性

类的属性

数据属性即变量,类的定义与函数极其类似,其实可以用函数的作用域来理解类的属性调用

类的数据属性

技术图片
 1 class Student:
 2     #学生类
 3     job = "study"
 4     def homework():
 5         print("学生在写作业")
 6     def exam(self):
 7         print("学生在考试")
 8 
 9 print(Student.job)
10 # study
11 print(dir(Student))#查看属性
12 # [‘__class__‘, ‘__delattr__‘, ‘__dict__‘, ‘__dir__‘, ‘__doc__‘, ‘__eq__‘, ‘__format__‘, ‘__ge__‘, ‘__getattribute__‘, ‘__gt__‘, ‘__hash__‘, ‘__init__‘, ‘__init_subclass__‘, ‘__le__‘, ‘__lt__‘, ‘__module__‘, ‘__ne__‘, ‘__new__‘, ‘__reduce__‘, ‘__reduce_ex__‘, ‘__repr__‘, ‘__setattr__‘, ‘__sizeof__‘, ‘__str__‘, ‘__subclasshook__‘, ‘__weakref__‘, ‘exam‘, ‘homework‘, ‘job‘]
13 print(Student.__dict__)#查看类的属性字典
14 # {‘__module__‘: ‘__main__‘, ‘job‘: ‘study‘, ‘homework‘: <function Student.homework at 0x000002172F3E9488>, ‘exam‘: <function Student.exam at 0x000002172F3E9510>, ‘__dict__‘: <attribute ‘__dict__‘ of ‘Student‘ objects>, ‘__weakref__‘: <attribute ‘__weakref__‘ of ‘Student‘ objects>, ‘__doc__‘: None}
15 print(Student.__dict__["homework"])
16 # <function Student.homework at 0x000001BE1A489488>
17 Student.__dict__["homework"]()
18 # 学生在写作业
19 Student.homework()
20 # 学生在写作业
21 Student.exam("qq")
22 # 学生在考试
23 
24 #特殊的类的属性
25 print(Student.__name__) #类的名字(字符串)
26 # Student
27 print(Student.__doc__) #类的文档字符串
28 # None
29 print(Student.__base__) #类的第一个父类(继承时再了解)
30 # <class ‘object‘>
31 print(Student.__bases__) #类的所有父类构成的元组
32 # (<class ‘object‘>,)
33 print(Student.__dict__) #类的属性
34 print(Student.__module__) #类定义所在的模块
35 # __main__
36 print(Student.__class__) #示例对应的类(仅新式类中)
37 # <class ‘type‘>
学生类

对象 

对象由类实例化而来

实例化

技术图片
 1 class Student:
 2     #学生类
 3     def __init__(self,name,gender,age):
 4         print("初始化函数开始运行")
 5         self.mingzi = name
 6         self.xingbie = gender
 7         self.nianji = age
 8         print("初始化函数运行结束")
 9     def homework(self):
10         print("[%s学生]在写作业"%self.mingzi)
11     def exam(self):
12         print("{%s岁}的[%s学生]在考试"%(self.nianji,self.mingzi))
13 
14 s1=Student("Alex","male",20) #实例化
15 # 初始化函数开始运行
16 # 初始化函数运行结束
17 print(s1.__dict__)
18 # {‘mingzi‘: ‘Alex‘, ‘xingbie‘: ‘male‘, ‘nianji‘: 20}
19 print(s1.__dict__["mingzi"])
20 # Alex
21 print(s1.nianji)
22 # 20
23 Student.exam(s1)
24 # {20岁}的[Alex学生]在考试
学生类的实例化

 

函数和类的属性

类属性又称为静态变量,或者是静态数据。这些数据与它们所属的类对象是绑定的,不依赖于任何类实例。在C++ 或Java中,这种类型的数据相当于在一个变量声明前加上static关键字。

技术图片
 1 class Student:
 2     #学生类
 3     nationality = "中国"
 4     def __init__(self,name,gender,age):
 5         self.mingzi = name
 6         self.xingbie = gender
 7         self.nianji = age
 8 
 9     def homework(self,classroom):
10         print("[%s学生]在(%s)写作业"%(self.mingzi,classroom))
11     def exam(self):
12         print("{%s岁}的[%s学生]在考试"%(self.nianji,self.mingzi))
13 
14 #查询
15 print(Student.nationality)
16 # 中国
17 
18 #修改
19 s1 = Student("Alex","male",40)
20 print(s1.nationality)
21 # 中国
22 
23 #增加
24 Student.pen = "pencil"
25 print(s1.pen)
26 # pencil
27 
28 #删除
29 del Student.pen
30 print(s1.pen)
31 # Wrong
32 
33 #增加函数属性
34 def course(self,course):
35     print("%s在上%s课"%(self.mingzi,course))
36 Student.course = course
37 s1.course("哲学")
38 # Alex在上哲学课
类属性——增删改查
技术图片
 1 class Student:
 2     #学生类
 3     nationality = "中国"
 4     def __init__(self,name,gender,age):
 5         self.mingzi = name
 6         self.xingbie = gender
 7         self.nianji = age
 8 
 9     def homework(self,classroom):
10         print("[%s学生]在(%s)写作业"%(self.mingzi,classroom))
11     def exam(self):
12         print("{%s岁}的[%s学生]在考试"%(self.nianji,self.mingzi))
13 
14 s1 =Student("ALLY","FEMALE",18)
15 
16 #查询
17 print(s1.mingzi)
18 # ALLY
19 s1.homework("B515")
20 # [ALLY学生]在(B515)写作业
21 
22 #增加
23 s1.pen = "pencil"
24 print(s1.pen)
25 # pencil
26 
27 #修改
28 s1.nianji = 30
29 print(s1.__dict__)
30 # {‘mingzi‘: ‘ALLY‘, ‘xingbie‘: ‘FEMALE‘, ‘nianji‘: 30, ‘pen‘: ‘pencil‘}
31 
32 #删除
33 del s1.mingzi
34 print(s1.__dict__)
35 # {‘xingbie‘: ‘FEMALE‘, ‘nianji‘: 18, ‘pen‘: ‘pencil‘}
数据属性——增删改查

 对象和实例属性的对比

技术图片
 1 country = "日本"
 2 class Chinese:
 3     country = "中国"
 4     def __init__(self,name):
 5         self.name = name
 6         print(">>>>",country)
 7 
 8 print(Chinese.__dict__)
 9 print(Chinese.country) #使用.的方式调用的,会去类里
10 # 中国
11 p1 = Chinese(JENNY) #不是使用.的方式调用的,跟类无关,不会去类里
12 # >>>> 日本
对象和实例属性
技术图片
 1 class Chinese:
 2     country = "中国"
 3     l = ["a","b"]
 4     def __init__(self,name):
 5         self.name = name
 6 p1=Chinese("Jenny")
 7 p1.l = [1,2,3] #修改了实例的属性
 8 print(Chinese.l)
 9 # [‘a‘, ‘b‘]
10 p1.l.append("c") #修改了类的属性
11 print(Chinese.l)
12 # [‘a‘, ‘b‘, ‘c‘]
实例和类的属性的修改补充

静态属性、类方法和静态方法

技术图片
 1 class Room:
 2     def __init__(self, name, owner, width, length, height):
 3         self.name = name
 4         self.owner = owner
 5         self.width = width
 6         self.length = length
 7         self.height = height
 8     @property#把函数属性变成了数据属性
 9     def call_area(self):
10         return self.length * self.width
11 
12 r1 = Room(503, Mr.Xu, 6, 3, 2.5)
13 r2 = Room(101, Jenny, 40, 20, 3)
14 print(r1.call_area)
15 # 18
16 print(r1.name)
17 # 503
静态属性
技术图片
 1 class Room:
 2     tag = 1
 3     def __init__(self, name, owner, width, length, height):
 4         self.name = name
 5         self.owner = owner
 6         self.width = width
 7         self.length = length
 8         self.height = height
 9 
10     @classmethod
11     def tell_tag(cls):
12         return cls.tag
13 
14 print(Room.tell_tag()) #无需实例化就可以实现类级别的方法
15 # 1
类方法
技术图片
 1 class Room:
 2     def __init__(self, name, owner, width, length, height):
 3         self.name = name
 4         self.owner = owner
 5         self.width = width
 6         self.length = length
 7         self.height = height
 8     @staticmethod #类的数据包,不跟类绑定,不跟实例绑定
 9     def sightseeing(a,b,c):
10         print("%s、%s和%s在看风景"%(a,b,c))
11 Room.sightseeing("a","b","c")
12 # a、b和c在看风景
静态方法

 

注意:staticmethod方法只是名义上的归属类管理,不能使用类变量和实例变量,是类的工具包

组合 

定义一个类,包括数据属性,这几个属性又可以是通过一个类实例化的对象,这就是组合

用途:

1、做关联

2、小的组成大的

技术图片
 1 class School:
 2     def __init__(self,schoolname,schooladdr):
 3         self.schoolname = schoolname
 4         self.schooladdr = schooladdr
 5 class Course:
 6     def __init__(self,coursename,price,period,school):
 7         self.coursename = coursename
 8         self.price = price
 9         self.period = period
10         self.school = school
11 
12 s1 = School("Tsinghua","Haidian")
13 s2 = School("DUT","Ganjingzi")
14 msg = """
15 1 清华
16 2 大工
17 """
18 
19 
20 while True:
21     print(msg)
22     menu = {
23         "1": s1,
24         "2": s2
25     }
26     choice = input("选择学校:")
27     school_obj = menu[choice]
28     coursename = input("课程名字:")
29     price = input("费用:")
30     period = input("课程周期:")
31     new_course = Course(coursename,price,period,school_obj)
32     print("课程【%s】授课地点在{%s}学校"%(new_course.coursename,new_course.school.schoolname))
33     # 1
34     # 清华
35     # 2
36     # 大工
37     #
38     # 选择学校:2
39     # 课程名字:python
40     # 费用:4000
41     # 课程周期:15
42     # week
43     # 课程【python】授课地点在
44     # {DUT}
45     # 学校
46 # c1 = Course("Linux",5000,"14week",s1)
47 # print(c1.__dict__)
48 # # {‘coursename‘: ‘Linux‘, ‘price‘: 5000, ‘period‘: ‘14week‘, ‘school‘: <__main__.School object at 0x00000247FA576390>}
49 # print(c1.school)
50 # # <__main__.School object at 0x000002442E3E72E8>
51 # print(c1.school.schoolname)
52 # # Tsinghua
学校选课系统

 

面向对象编程的三大特性

继承

类的继承跟现实生活中的父、子、孙的继承关系一样,父类称为基类。

Python中的类的继承分为:单继承和多继承

1  class ParentClass1:
2      pass
3  class ParentClass2:
4      pass
5  class SubClass(ParentClass1): #单继承
6      pass
7  class SubClass(ParentClass1,ParentClass2): #多继承
8      pass

 

子继承到底继承了父类的什么属性?

子类继承了父类的所有属性

 1 class Parent:
 2     money  = 10000
 3     def __init__(self,name):
 4         print("Dady")
 5         self.name = name
 6     def hit_son(self):
 7 
 8         print("%s is hitting son"%self.name)
 9 class Son(Parent): #单继承
10     money = 2000
11     pass
12 s1 = Son("Alex")
13 print(s1.name)
14 print(s1.hit_son())
15 # Dady
16 # Alex
17 # Alex is hitting son
18 print(s1.money)
19 print(Parent.money)
20 # 2000
21 # 10000

 

什么时候用继承?

1、当类之间有显著差异,且较小的类是较大的类所需要的组件时,用组合比较好

2、当类之间有很多相同功能,提取这些共同功能做成基类,用继承比较好

继承同时具有两种含义

1、继承基类的方法,并且做出自己的改变或者扩展(代码重用)——少用

2、声明某个子类兼容于某基类,定义一个接口类,子类继承接口类,并且实现接口中定义的方法

继承的第二种含义非常重要,它叫“接口继承”。

接口继承实际上要求“做出一个良好的抽象,这个抽象规定了一个兼容接口,使得外部调用者无需关心具体细节,可一视同仁地处理实现了特定接口的所有对象”——这在程序设计上叫做“归一化”。

归一化使得高层的外部使用者可以不加区分地处理所有接口兼容的对象集合——就像linux的范文件概念一样,所有东西都可以当做文件处理,不必关心它是内存、硬盘网络还是屏幕

继承顺序:

1、Python的类可以继承多个类,而Java和C#只能继承一个

2、Python的类如果继承多个类,那么找寻的方式是深度优先和广度优先。

技术图片
 1 class A:
 2     def test(self):
 3         print("A")
 4 class B(A):
 5     def test(self):
 6         print("B")
 7 class C(A):
 8     def test(self):
 9         print("C")
10 class D(B):
11     def test(self):
12         print("D")
13 class E(C):
14     def test(self):
15         print("E")
16 class F(D,E):
17     def test(self):
18         print("F")
19 print(F.__mro__)
20 # (<class ‘__main__.F‘>, <class ‘__main__.D‘>, <class ‘__main__.B‘>, <class ‘__main__.E‘>, <class ‘__main__.C‘>, <class ‘__main__.A‘>, <class ‘object‘>)
21 # order:F->D->B->E->C->A
Python3广度继承

 

子类中调用父类方法

技术图片
 1 class Animal:
 2     def __init__(self,name,bark):
 3         self.name = name
 4         self.bark = bark
 5 class Cat(Animal):
 6     def __init__(self,name,bark,kind):
 7         self.kind = kind
 8 c1 = Cat("小小","喵喵","英短")
 9 print(c1.kind)
10 # 英短
子类中调用父类的方法

super().方法:可以修改父类名称,不影响子类

 1 class Animal:
 2     def __init__(self,name,bark):
 3         self.name = name
 4         self.bark = bark
 5 class Cat(Animal):
 6     def __init__(self,name,bark,kind):
 7         super().__init__(name,bark)
 8         self.kind = kind
 9 c1 = Cat("小小","喵喵","英短")
10 print(c1.name)
11 # 小小

 

以上是关于Python学习(十三)—— 面向对象程序设计的主要内容,如果未能解决你的问题,请参考以下文章

Java学习笔记之十三初探Java面向对象的过程及代码实现

Python基础篇第十三篇:面向对象

面向对象的设计模式(十三),解释器模式

Python基础(二十三):面向对象之继承介绍

python 面向对象十三 枚举类

二十三种设计模式