python【第六篇】面向对象编程

2023-05-24,,

面向对象编程

一、编程范式:编程的方法论。程序员编程的“套路”及“特点”特点总结,抽象成方法、规范。

二、面向对象编程介绍:

1.描述

  世界万物,皆可分类;世间万物,皆为对象;只要是对象,就肯定属于某种品类;只要是对象,就肯定有一定的属性。

  opp编程(面向对象编程)的抽象机制是将待解问题抽象为面向对象的程序中的对象。利用封装使每个对象都拥有个体的身份。程序便是成堆的对象,彼此通过消息的传递,请求其它对象 进行工作。也可以说opp编程是利用“类”和“对象”来创建各种模型来实现对真实世界的描述。

2.优势(好处)

  使程序的维护和扩展变简单;使他人更容易理解代码逻辑;大大提高程序开发效率;使他人更容易理解代码逻辑,使团队开发更从容。

3.面向对象有几个特性:

类(class)

  一个类就是对一类具有相同属性的对象的抽象。(可以理解为类型、原型)。类中定义这些对象都具备的属性、共同方法。比如:卡车1,小汽车1,房车1...等对象都具有轮子、方向盘、发动机...等属性和载东西、开动等方法,那么我们可以提取它们的这些属性和方法,抽象出汽车这种“类”。那么凡是汽车都具有轮子、方向盘、发动机...等属性和载东西、开动等方法。

对象(object)

  一个对象即是一个类的实例化后实例,每个对象都是其类中的一个实体(把一个类变成一个具体对象的过程叫实例化)。

  物以类聚——就是说明:类是相似对象的集合。类中的对象可以接受相同的消息。换句话说:类包含和描述了“具有共同特性(数据元素)和共同行为(功能)”的一组对象。

比如:苹果、梨、橘子等等对象都属于水果类。

  一个类必须经过实例化后方可在程序中调用,一个类可以实例化多个对象,每个对象亦可以有不同的属性,就像人类是指所有人,每个人是指具体的对象,人与人之前有共性,亦有不同。

封装(Encapsulation 

  封装(有时也被称为信息隐藏)就是把数据和行为结合在一个包中,并对对象的使用者隐藏数据的实现过程。信息隐藏是面向对象编程的基本原则,而封装是实现这一原则的一种方 式。

  封装使对象呈现出“黑盒子”特性,这是对象再利用和实现可靠性的关键步骤。也就是说在类中对数据的赋值、内部调用等对外部用户是透明的(不可见的),这使类变成了一个胶囊或容器,里面包含着类的数据和方法。

继承(Inheritance

  继承的思想就是允许在已存在类的基础上构建新的类。一个子类能够继承父类的所有成员,包括属性和方法。

  继承的主要作用:通过实现继承完成代码重用;通过接口继承完成代码被重用。继承是一种规范的技巧,而不是一种实现的技巧。

多态(Polymorphism

  多态是面向对象的重要特性,多态提供了“接口与实现分离”。多态不但能改善程序的组织架构及可读性,更利于开发出“可扩充”的程序。简单点说:“一个接口,多种实现”,指一个基类中派生出了不同的子类,且每个子类在继承了同样的方法名的同时又对父类的方法做了不同的实现,这就是同一种事物表现出的多种形态。
  编程其实就是一个将具体世界进行抽象化的过程,多态就是抽象化的一种体现,把一系列具体事物的共同点抽象出来, 再通过这个抽象的事物, 与不同的具体事物进行对话。
对不同类的对象发出相同的消息将会有不同的行为。比如,你的老板让所有员工在九点钟开始工作, 他只要在九点钟的时候说:“开始工作”即可,而不需要对销售人员说:“开始销售工作”,对技术人员说:“开始技术工作”, 因为“员工”是一个抽象的事物, 只要是员工就可以开始工作,他知道这一点就行了。至于每个员工,当然会各司其职,做各自的工作。
多态允许将子类的对象当作父类的对象使用,某父类型的引用指向其子类型的对象,调用的方法是该子类型的方法。这里引用和调用方法的代码编译前就已经决定了,而引用所指向的对象可以在运行期间动态绑定。

  继承是多态的基础。多态是继承的目的。

  合理的运用基于类继承的多态、基于接口继承的多态和基于模版的多态,能增强程序的简洁性、灵活性、可维护性、可重用性和可扩展性。

  面向对象是建立在其他编程技术之上的,是以前的编程思想的自然产物。如果说结构化软件设计是将函数式编程技术应用到命令式语言中进行程序设计,面向对象编程不过是将函数式模型应用到命令式程序中的另一途径,此时,模块进步为对象,过程龟缩到class的成员方法中。OOP的很多技术——抽象数据类型、信息隐藏、接口与实现分离、对象生成功能、消息传递机制等等,很多东西就是结构化软件设计所拥有的、或者在其他编程语言中单独出现。但只有在面向对象语言中,他们才共同出现,以一种独特的合作方式互相协作、互相补充。

4.补充几点:

(1)接口

  每个对象都有接口。接口不是类,而是对符合接口需求的类所作的一套规范。接口说明类应该做什么但不指定如何作的方法。一个类可以有一个或多个接口。

(2)方法

  方法决定了某个对象究竟能够接受什么样的消息。面向对象的设计有时也会简单地归纳为“将消息发送给对象”。

三、示例代码和讲解

1.类语法、属性、方法、类变量、实例变量:

 # _*_ coding:utf-8 _*_
 __author__ = "ZingP"

 # 定义类
 class Role:
     n = 123                   # 类变量
     name = "我是类name"
     n_list = []
     def __init__(self, name, role, weapon, life_value=100, money=15000):
         # 构造函数
         # 在实例化时做一些类的初始化工作
         self.name = name      # 实例变量(静态属性),作用域就是实例本身
         self.role = role
         self.weapon = weapon
         self.life_value = life_value
         self.money = money

     def shoot(self):            # 类的方法、功能(动态属性)
         print("Shooting...")

     def got_shot(self):
         print("%s : i  got shoot...f**k"%self.name)

     def buy_gun(self,gun_name):
         print("%s buy a %s..."%(self.name, gun_name))

 r1 = Role("zing-p", "Police", "AK47")
 r2 = Role("alex", "terrorist", "B22")
 print(Role.n)        # ---->123        解释:可直接调用类变量
 print(Role.name)     # ---->我是类name
 print(r1.n)          # ---->123
 print(r1.name)       # ---->zing-p     解释:实例变量(静态属性),作用域就是实例本身。所以优先找实例变量,再找类变量
 r1.buy_gun("B22")    # ---->zing-p buy a B22...

 r1.name = "张三"
 print(r1.name)       # ---->张三       解释:可以更改实例变量的值

 r1.bullet_prove = True      # 增加r1这个实例的属性
 print(r1.bullet_prove)      # ---->True   解释:

 r1.n_list.append("r1form")  # 更改了类变量n_list的值
 print(r2.n_list)            # ---->['r1form']

2.析构函数、私有属性、私有方法示例:

 # _*_ coding:utf-8 _*_
 __author__ = "ZingP"
 # 定义类
 class Role:

     def __init__(self, name, role, weapon, life_value=100, money=15000):
         # 构造函数
         # 在实例化时做一些类的初始化工作
         self.name = name      # 实例变量(静态属性),作用域就是实例本身
         self.role = role
         self.weapon = weapon
         self.__life_value = life_value # 定义私有属性 类内部可以访问  外部不能访问
         self.money = money

     def show_status(self):
         print("%s: weapon:%s, life_value:%s." % (self.name,
                                                  self.weapon,
                                                  self.__life_value))

     def __del__(self):
         print("%s 所在实例已经被释放了。" % self.name)

     def shoot(self):            # 类的方法、功能(动态属性)
         print("Shooting...")

     def __got_shot(self):       # 私有化方法
         print("%s : i  got shoot...f**k" % self.name)

     def buy_gun(self, gun_name):
         print("%s buy a %s..." % (self.name, gun_name))

 r1 = Role("zing-p", "Police", "AK47")
 r2 = Role("alex", "terrorist", "B22")

 # 运行结果:
 # AttributeError: 'Role' object has no attribute '__life_value'  #说明私有属性不能从外部访问
 # alex 所在实例已经被释放了。
 # zing-p 所在实例已经被释放了。

 # print(r1.name, r1.weapon)
 # print(r2.name, r2.weapon)
 # 运行结果:
 # zing-p AK47
 # alex B22
 # zing-p 所在实例已经被释放了。
 # alex 所在实例已经被释放了。

 # print(r1.name, r1.weapon)
 # del r1
 # print(r2.name, r2.weapon)
 # 运行结果:
 # zing-p AK47
 # zing-p 所在实例已经被释放了。
 # alex B22
 # alex 所在实例已经被释放了。

 # print(r1.show_status())
 # 运行结果:
 # zing-p: weapon:AK47, life_value:100.        # 通过访问内部的方法、这个内部方法调用了私有属性
 # None                                        # show_status()无返回值
 # zing-p 所在实例已经被释放了。               # 析构函数自动执行
 # alex 所在实例已经被释放了。                 # 析构函数自动执行

3.类的继承:

 # _*_ coding:utf-8 _*_
 __author__ = "ZingP"

 # 经典式类写法
 # class People:

 # 新式类写法
 class People(object):
     def __init__(self, name, age):
         self.name = name
         self.age  = age

     def eat(self):
         print("%s is eating...." % self.name)

     def sleep(self):
         print("%s is sleeping..." % self.name)

 class Man(People):
     def __init__(self, name, age, money):
         People.__init__(self, name, age)   # 等价于这么写: super(Man, self).__init__(name, age)
         self.money = money
         print("%s 一出生就有%s $." % (self.name, money))

     def smoke(self):
         print("%s is smoking..." % self.name)

     def sleep(self):
         People.sleep(self)             # 调用父类的sleep方法
         print("Man is sleeping...")    # 对父类中的sleep方法增加功能

 class Women(People):
     def give_birth(self):
         print("%s is given birth a baby." % self.name)

 m1 = Man("zing-p", 25, 10)
 w1 = Women("angelababy", 27)
 m1.eat()
 m1.smoke()
 m1.sleep()
 w1.give_birth()
 # 输出结果:
 # zing-p is eating....     #  继承了父类eat方法
 # zing-p is smoking...     #  自己的smoke方法
 # zing-p is sleeping...
 # Man is sleeping...
 # angelababy is given birth a baby.

4.类的多继承:

  # _*_ coding:utf-8 _*_
 __author__ = "ZingP"

 class People(object):
     friends = []
     def __init__(self, name, age):
         self.name = name
         self.age = age

     def eat(self):
         print("%s is eating...." % self.name)

     def sleep(self):
         print("%s is sleeping..." % self.name)

 class Relation(object):
     def makefriends(self,obj):
         print("%s is making friends with %s." % (self.name, obj.name))
         self.friends.append(obj)  # 添加的是一个对象,不应该是obj.name,因为obj.name是个字符串。

 class Man(People, Relation):
     def __init__(self, name, age, money):
         super(Man, self).__init__(name, age)
         self.money = money

     def smok(self):
         print("%s is smoking..." % self.name)

     def sleep(self):
         People.sleep(self)
         print("Man is sleeping...")

 class Women(People, Relation):
     def give_birth(self):
        print("%s is given birth a baby." % self.name)

 m1 = Man("zing-p", 25, 10)
 w1 = Women("angelababy", 27)

 m1.makefriends(w1)
 print(m1.friends[0].name)  # m1.friends[0]其实是w1这个对象实例,具有name属性,即便是W1的name更改后,也会输出更改后的name。

 # 输出结果:
 # zing-p is making friends with angelababy.
 # anglelababy

5.类的继承及类的相互关联:

 # _*_ coding:utf-8 _*_
 __author__ = "ZingP"

 # 定义一个School(学校)类
 class School(object):  # object是基类
     def __init__(self, name, addr):
         self.name = name
         self.addr = addr
         self.students = []
         self.staffs = []

     def enroll(self, stu_obj):
         print("为学员%s办理注册手续" % stu_obj.name)
         self.students.append(stu_obj)

     def hire(self, staff_obj):
         print("雇佣新员工:%s。" % (staff_obj.name))
         self.staffs.append(staff_obj)

 # 定义一个SchoolMember(学校成员)类
 class SchoolMember(object):
     def __init__(self, name, age, sex):
         self.name = name
         self.age = age
         self.sex = sex

     def tell(self):
         pass

 # 定义一个Teacher(老师)类,并继承SchoolMember类
 class Teacher(SchoolMember):
     def __init__(self, name, age, sex, salary, course):
         super(Teacher, self).__init__(name, age, sex)
         self.salary = salary
         self.course = course

     def tell(self):
         print('''
         -------Info of Teacher:%s------
         Name:%s
         Age:%s
         Sex:%s
         Salary:%s
         Course:%s
         ''' % (self.name, self.name, self.age, self.sex, self.salary, self.course))

     def teach(self):
         print("%s is teaching %s course" % (self.name, self.course))

 # 定义一个Student(学生)类,并继承SchoolMember类
 class Student(SchoolMember):
     def __init__(self, name, age, sex, stu_id, grade):
         super(Student, self).__init__(name, age, sex)
         self.stu_id = stu_id
         self.grade = grade

     def tell(self):
         print('''
                 -------Info of Student:%s------
                 Name:%s
                 Age:%s
                 Sex:%s
                 Stu_id:%s
                 Grade:%s
                 ''' % (self.name, self.name, self.age, self.sex, self.stu_id, self.grade))

     def pay_tuition(self, tuition_fee):
         print("学生%s交学费:%s$。" % (self.name, tuition_fee))

 school = School("清华大学", "五道口")

 s1 = Student("李小龙", 22, "男", 1001, "大四")
 s2 = Student("杨颖", 18, "女", 1002, "大四")

 t1 = Teacher("张老师", 40, "男", 20000, "高数")
 t2 = Teacher("李老师", 33, "女", 8000, "毛概")

 s1.pay_tuition(5500)              # 学生李小龙交学费:5500$。  # 执行S1这个实例的pay方法
 school.enroll(s1)                 # 为学员李小龙办理注册手续  # 执行school这个实例的enroll方法
 print(school.students[0])         # <__main__.Student object at 0x01D28190> # 执行school这个实例的enroll方法后
                                                                             # 得到一个student列表,列表中装有s1这个实例对象
 print(school.students[0].grade)   # 大四 # school.students[0]是s1实例对象

 t2.teach()                        # 李老师 is teaching 毛概 course
 school.hire(t2)                   # 雇佣新员工:李老师。
 print(school.staffs[0])           # <__main__.Teacher object at 0x01CF81D0>
 

6.多态(一定要记住“一个接口多种实现”)

6.1我们先看“一个接口多种实现”的一种实现方法:

 # _*_ coding:utf-8 _*_
 __author__ = "ZingP"

 class Animal:
     def __init__(self, name):
         self.name = name

 class Cat(Animal):
     # 猫叫
     def talk(self):
         print("The cat %s is mewing..." % self.name)

 class Dog(Animal):
     # 狗吠
     def talk(self):
         print("The dog %s is barking..." % self.name)

 c = Cat('Missy')
 d = Dog('Lassie')

 #  这样基本能实现“一个接口、多种实现”的效果:
 # def animal_talk(obj):
 #     obj.talk()
 # animal_talk(c)      # The cat Missy is mewing...
 # animal_talk(d)      #The dog Lassie is barking...

6.2再来看看多态:

 # _*_ coding:utf-8 _*_
 __author__ = "ZingP"

 class Animal:
     def __init__(self, name):
         self.name = name

     @staticmethod
     def animal_talk(obj):
         obj.talk()

 class Cat(Animal):
     # 猫叫
     def talk(self):
         print("The cat %s is mewing..." % self.name)

 class Dog(Animal):
     # 狗吠
     def talk(self):
         print("The dog %s is barking..." % self.name)

 c = Cat('Missy')
 d = Dog('Lassie')

 #  这样基本能实现“一个接口、多种实现”的效果:
 # def animal_talk(obj):
 #     obj.talk()
 Animal.animal_talk(c)      # The cat Missy is mewing...
 Animal.animal_talk(d)      # The dog Lassie is barking...
***新式类和经典类区别:类的继承顺序不同。python3.X:经典类和新式类都是按广度优先继承的。python2.X:  经典类:按深度优先来继承的(在python中深度优先效率比广度优先的效率低)。  新式类:按广度优先来继承的。

本节作业: 选课系统


角色:学校、学员、课程、讲师
要求:
1. 创建北京、上海 2 所学校
2. 创建linux , python , go 3个课程 , linux\py 在北京开, go 在上海开
3. 课程包含,周期,价格,通过学校创建课程 
4. 通过学校创建班级, 班级关联课程、讲师
5. 创建学员时,选择学校,关联班级
6. 创建讲师角色时要关联学校, 
7. 提供两个角色接口
7.1 学员视图, 可以注册, 交学费, 选择班级,
7.2 讲师视图, 讲师可管理自己的班级, 上课时选择班级, 查看班级学员列表 , 修改所管理的学员的成绩 
7.3 管理视图,创建讲师, 创建班级,创建课程


8. 上面的操作产生的数据都通过pickle序列化保存到文件里


python【第六篇】面向对象编程的相关教程结束。

《python【第六篇】面向对象编程.doc》

下载本文的Word格式文档,以方便收藏与打印。