4、第六 - 类的特性讲解

类的特性::封装、继承、多态。 “一个接口,多种实现”

类的特性讲解

1、类的封装
作用防止内部对象数据不能被外部随意修改;使外部程序不需要关注对象内部的构造,只需要通过对象对外提供的接口进行访问。可分为类的公有属性、私有属性。

把功能实现的细节不对外暴露;

私有属性:(对外部是不可见的、对内部是可见的)
__private_attr_name = value
def get_heart(self) #对外部提供只读访问接口

return self.__heart
r1._Role__heart :强制访问私有属性

 

公有属性:
在类里面定义的方法,叫做公有属性

 

 2、类的继承

     1)、类的继承讲解

  面向对象编程(OOP) 语言的一个主要功能就是“继承”。继承是指这样一种能力:它可以使用现有类的所有功能,并在无需重新编写原来的类的情况下对这些功能进行扩展。使用继承时,有一点需要注意,那就是两个类之间的关系应该是“属于”关系

定义:
  1、通过继承创建的新类称为“子类”或“派生类”。
  2、被继承的类称为“基类”、“父类”或“超类”。
  3、继承的过程,就是从一般到特殊的过程。
 要实现继承,可以通过“继承”(Inheritance)和“组合”(Composition)来实现。一个子类可以继承多个基类。但是一般情况下,一个子类只能有一个基类,要实现多重继承,可以通过多级继承来实现。(注意:建议最多就是三层。)

继承概念的实现方式主要有2类:实现继承、接口继承。
  1、实现继承是指使用基类的属性和方法而无需额外编码的能力;
  2、接口继承是指仅使用属性和方法的名称、但是子类必须提供实现的能力(子类重构爹类方法);

 面向对象编程开发范式大致为:划分对象→抽象类→将类组织成为层次化结构(继承和合成) →用类与实例进行设计和实现几个阶段

举例:

A、简单例子类的继承:

class Person(object): #定义类

    def talk(name): #类的调用方法
        print("Who's Talking? It's me.-- %s " % name)

class BlckPerson(Person): #简单的子类调用父类
      pass

b = BlckPerson
b.talk("chen") #直接调用父类中的方法
输出:
Who's Talking? It's me.-- chen 

 B、类继承中,父类与子类中 self 中参数传递:由子类中self 传参到 父类 中。

#conding:utf-8
class Person(object): #定义类
    def __init__(self,name,age):
        self.name = name
        self.age = age
        self.other = "normal"

    def talk(self): #类的调用方法
        print("Who's Talking? It's me.-- %s " % self.name)

class BlckPerson(Person): #简单的子类调用父类
      def __init__(self,name,age,height):
          Person.__init__(self,name,age) #把父类的公有属性,也定义继承过来。
          self.height = height

      def size(self):
          print ("%s 身高是 %s" % (self.name,self.height))

b = BlckPerson('chen1203',25,'180cm') #调用类并传值。
b.talk() #直接调用父类中的方
b.size()   #在子类中,没有定义self.name,继承父类后,可以直接调用
输出:
Who's Talking? It's me.-- chen1203 
chen1203 身高是 180cm

 C、类的单继承示例(复杂度高点)

class SchoolMember(object):

    member = 0

    '''定义共同类别'''
    def __init__(self,name,age,sex):
        self.name = name
        self.age = age
        self.sex = sex
        self.enroll()

    def enroll(self):
        '''注册'''
        print ("A New School Member Enrolled ,It's Name: %s" % self.name)
        SchoolMember.member += 1

    def tell(self):
        '''打印信息'''
        print("----------%s-------" % self.name)
        for k,v in  self.__dict__.items():
            print(k,v)
        print("-----END-----")

    """
    def __del__(self): #析构函数
        '''开除学生'''
        print('开除[%s]' % self.name)
        self.member -= 1  
    """
    
class Tearcher(SchoolMember):
    '''老师'''
    def __init__(self,name,age,sex,salary,course):
        SchoolMember.__init__(self,name,age,sex) #经典类的调用
        self.salary = salary
        self.course = course

    def Tearching(self):
        print("Teacher [%s] is tearching [%s] " % self.name,self.course)

class Students(SchoolMember):
    '''' 学生'''
    def __init__(self,name,age,sex,course,fee):
        SchoolMember.__init__(self,name,age,sex)
        self.course = course
        self.fee = fee
        self.amount = 0

    def pay_fee(self,amount):
        print('student [%s] has just paied [%s]' % (self.name, amount))
        self.amount += amount

T1 = Tearcher('chen1203',25,'M',2000,"PHP")
T1.tell()
S1 = Students('jianhui', 30, 'M', 'python', 3000)
S1.tell()
S2 = Students('huaming', 22, 'M', 'python', 1000)
S2.tell()
print(SchoolMember.member)

输出:
A New School Member Enrolled ,It's Name: chen1203
----------chen1203-------
course PHP
sex M
salary 2000
name chen1203
age 25
-----END-----
A New School Member Enrolled ,It's Name: jianhui
----------jianhui-------
fee 30000
course python
sex M
amount 0
name jianhui
age 30
-----END-----
A New School Member Enrolled ,It's Name: huaming
----------huaming-------
fee 1000
course python
sex M
amount 0
name huaming
age 22
-----END-----
会员总数:3

D、类的多继承示例(用的不多,一般都是使用单继承)。有些语言可能不支持,但Python是支持的

接着跟上面的例子,举例如下:

class SchoolMember(object):  

    member = 0

    '''定义共同类别'''
    def __init__(self,name,age,sex):
        self.name = name
        self.age = age
        self.sex = sex
        self.enroll()

    def enroll(self):
        '''注册'''
        print ("A New School Member Enrolled ,It's Name: %s" % self.name)
        SchoolMember.member += 1

    def tell(self):
        '''打印信息'''
        print("----------%s-------" % self.name)
        for k,v in  self.__dict__.items():
            print(k,v)
        print("-----END-----")

    """
    def __del__(self): #析构函数
        '''开除学生'''
        print('开除[%s]' % self.name)
        self.member -= 1  
    """

class School(object):
    def open_branch(self,addr):
        print ("Opening a new branch in ",addr)

class Tearcher(SchoolMember,School):  #把以上的两个类进行继承。主要在这个位置进行添加
    '''老师'''
    def __init__(self,name,age,sex,salary,course):
        SchoolMember.__init__(self,name,age,sex) #经典类的调用
        self.salary = salary
        self.course = course

    def Tearching(self):
        print("Teacher [%s] is tearching [%s] " % self.name,self.course)

class Students(SchoolMember,School):
    '''' 学生'''
    def __init__(self,name,age,sex,course,fee):
        SchoolMember.__init__(self,name,age,sex)
        self.course = course
        self.fee = fee
        self.amount = 0

    def pay_fee(self,amount):
        print('student [%s] has just paied [%s]' % (self.name, amount))
        self.amount += amount

T1 = Tearcher('chen1203',25,'M',2000,"PHP")
S1 = Students('jianhui', 30, 'M', 'python', 30000)
S2 = Students('huaming', 22, 'M', 'python', 1000)
S1.open_branch("广州")

输出:

A New School Member Enrolled ,It's Name: chen1203
A New School Member Enrolled ,It's Name: jianhui
A New School Member Enrolled ,It's Name: huaming
Opening a new branch in  广州
类的多继承

2)、新式类与经典类

Python 2.x中默认都是经典类,只有显式继承了object才是新式类
Python 3.x中默认都是新式类,不必显式的继承object
注意:以后的使用中,最好统一使用新式类,调用也是用super的方法

新式类与经典类的区别

语法区别:(新的写法中,都是会按照新式类的写法来走)
class Persion(object): #新式类
class Persion: #经典类

调用方法的区别:(针对类的多继承中的例子)
SchoolMember.__init__(self,name,age,sex)#经典类的调用
super(Tearcher,self).__init__(name,age,sex) #新式类的调用

继承搜索的顺序发生了改变:
@ 经典类多继承属性搜索顺序: 先深入继承树左侧,再返回,开始找右侧;
@ 新式类多继承属性搜索顺序: 先水平搜索,然后再向上移动 

A、新式类与经典类的区别:新式类对象可以直接通过__class__属性获取自身类型:type 

举例:

"""python 3 中执行"""

# -*- coding:utf-8 -*-
class E:
    #经典类
    pass

class E1(object):
    #新式类
    pass

e = E()
print ("经典类")
print (e)
print (type(e))
print (e.__class__)

e1 = E1()
print ("新式类")
print (e1)
print (type(e1))
print (e1.__class__)

输出:
经典类
<__main__.E object at 0x102978748>
<class '__main__.E'>
<class '__main__.E'>
新式类
<__main__.E1 object at 0x102978828>
<class '__main__.E1'>
<class '__main__.E1'>

====================================

"""python 2 中执行"""

# -*- coding:utf-8 -*-
class E:
    #经典类
    pass

class E1(object):
    #新式类
    pass

e = E()
print ("经典类")
print (e)
print (type(e))
print (e.__class__)

e1 = E1()
print ("新式类")
print (e1)
print (type(e1))
print (e1.__class__)

输出:

经典类
<__main__.E instance at 0x10b431cb0>
<type 'instance'>
__main__.E
新式类
<__main__.E1 object at 0x10b420250>
<class '__main__.E1'>
<class '__main__.E1'>



结论:新式类对象可以直接通过__class__属性获取自身类型:type ;在python 3 中经典类与新式类是一致的。python2 的输出中,区别比较大
经典类VS新式类的区别

B、新式类与经典类的继承搜索的顺序区别

举例说明:

 

(1)、经典类与新式类在python3中的执行顺序是:新式类与经典类都是 D->B、C->A(先水平搜索,然后再向上移动)

举例如下:

 1 """ python3中执行"""
 2 """新式类"""
 3 class A(object):
 4     def __init__(self):
 5         self.n = "A"
 6 
 7 class B(A):
 8    pass
 9 
10 class C(A):
11     def __init__(self):
12         self.n = "C"
13 
14 class D(B,C):
15     pass
16 
17 d = D()
18 print(d.n)
19 
20 """经典类"""
21 class A1:
22     def __init__(self):
23         self.n = "A1"
24 
25 class B1(A1):
26    pass
27 
28 class C1(A1):
29     def __init__(self):
30         self.n = "C1"
31 
32 class D1(B1,C1):
33     pass
34 
35 d1 = D1()
36 print(d1.n)
37 
38 输出:
39 C
40 C1
python3中执行

(2)、经典类与新式类在python2中的执行顺序是:新式类是 D->B、C->A (先水平搜索,然后再向上移动);经典类是 D->B->A-C 或者是 D->C->B->A (先深入继承树左侧,再返回,开始找右侧。当把右侧的class C pass掉之后,继承的顺序有变更为D->C->B->A;

举例如下:

 1 """新式类"""
 2 class A(object):
 3     def __init__(self):
 4         self.n = "A"
 5 
 6 class B(A):
 7    pass
 8 
 9 class C(A):
10     def __init__(self):
11         self.n = "C"
12 
13 class D(B,C):
14     pass
15 
16 d = D()
17 print d.n
18 
19 
20 """经典类"""
21 class A1:
22     def __init__(self):
23         self.n = "A1"
24 class B1(A1):
25      pass
26 class C1(A1):
27     def __init__(self):
28         self.n = "C1"
29 
30 class D1(B1,C1):
31     pass
32 
33 d1 = D1()
34 print d1.n
35 
36 输出:
37 C
38 A1
python2中执行

 

3、类的多态实例 

   多态性(polymorphisn)是允许你将父对象设置成为和一个或更多的他的子对象相等的技术,赋值之后,父对象就可以根据当前赋值给它的子对象的特性以不同的方式运作。简单的说,就是一句话:允许将子类类型的指针赋值给父类类型的指针。

   多态的作用是什么呢?封装可以隐藏实现细节,使得代码模块化;继承可以扩展已存在的代码模块(类);它们的目的都是为了——代码重用。而多态则是为了实现另一个目的——接口重用!多态的作用,就是为了类在继承和派生的时候,保证使用“家谱”中任一类的实例的某一属性时的正确调用。

  举例:

 1 # _*_coding:utf-8_*_
 2 
 3 class Animal(object):
 4     def __init__(self, name):  # Constructor of the class
 5         self.name = name
 6 
 7     def talk(self):  # Abstract method, defined by convention only
 8         raise NotImplementedError("Subclass must implement abstract method")
 9 
10 
11 class Cat(Animal):
12     def talk(self):
13         print('%s: 喵喵喵!' % self.name)
14 
15 
16 class Dog(Animal):
17     def talk(self):
18         print('%s: 汪!汪!汪!' % self.name)
19 
20 
21 def func(obj):  # 一个接口,多种形态
22     obj.talk()
23 
24 
25 c1 = Cat('小晴')
26 d1 = Dog('李磊')
27 
28 func(c1)
29 func(d1)
30 输出
31 小晴: 喵喵喵!
32 小磊: 汪!汪!汪!
多态举例

 

作业:选课系统

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

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

 

转载于:https://www.cnblogs.com/chen170615/p/8463181.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值