Python面向对象的三大特征(封装、继承、多态)、继承详解

面向对象技术简介

  • 类(Class): 用来描述具有相同的属性和方法的对象的集合。它定义了该集合中每个对象所共有的属性和方法。对象是类的实例。
  • 类变量:类变量在整个实例化的对象中是公用的。类变量定义在类中且在函数体之外。类变量通常不作为实例变量使用。
  • 数据成员:类变量或者实例变量用于处理类及其实例对象的相关的数据。
  • 方法重写:如果从父类继承的方法不能满足子类的需求,可以对其进行改写,这个过程叫方法的覆盖(override),也称为方法的重写。
  • 实例变量:定义在方法中的变量,只作用于当前实例的类。
  • 继承:即一个派生类(derived class)继承基类(base class)的字段和方法。继承也允许把一个派生类的对象作为一个基类对象对待。例如,有这样一个设计:一个Dog类型的对象派生自Animal类,素以Dog也是一个Animal。继承可以让子类具有父类的特性,提高了代码的复用性。继承从设计上是一个增量进化,原有父类设计不变的情况下,可以增加新的功能,或者改进已有的算法
  • 实例化:创建一个类的实例,类的具体对象。
  • 方法:类中定义的函数。
  • 对象:通过类定义的数据结构实例。对象包括两个数据成员(类变量和实例变量)和方法。

和其它编程语言相比,Python 在尽可能不增加新的语法和语义的情况下加入了类机制。

封装

隐藏对象的属性和实现细节,只对外提供必要的方法,相当于将“细节封装起来”,只对外暴露“相关的调用方法”。封装可以通过“私有属性、私有方法”的方式,实现封装。

实例 
如果要让内部属性不被外部访问,可以把属性的名称前加上两个下划线__,在Python中,实例的变量名如果以__开头,就变成了一个私有变量(private),只有内部可以访问,外部不能访问。 
代码如下:

class Student(object):

    def __init__(self, name, score):
        self.__name = name
        self.__score = score

    def print_score(self):
        print('%s: %s' % (self.__name, self.__score))

如果外部代码要获取name和score,可以给Student类增加get_nameget_score这样的方法:

class Student(object):
    #这里的代码和上面一样,定义两个私有属性__name和__score
    ...

    def get_name(self):
        return self.__name

    def get_score(self):
        return self.__score

同时又允许外部代码修改score可以再给Student类增加set_score方法:

class Student(object):
    #代码同上
    ...

    def set_score(self, score):
        self.__score = score

继承 

我们不想把同一段代码写好几次,之前使用的函数避免了这种情况。但现在又有个更微妙的问题。如果已经有了一个类,又想建立一个非常类似的类,只是添加几个方法。 
比如有人类,我们又想在人类的基础上建立学生类、医生类,教师类。因为他们都具有共同的属性和方法,比如都有 姓名 、年龄 、性别 等共同属性,还有吃饭、睡觉等共同方法。我们就可以写一个人类作为父类,包括姓名、年龄、性别等属性和吃饭睡觉等方法。然后再写多个子类继承父类的这些属性和方法。
但需要注意的是,父类的私有属性和方法不会被子类继承

 子类对父类方法的重写 

子类继承父类时,子类的方法签名和父类一样,此时子类重写了父类的方法,当生成子类对象时,调用的是子类重写的方法。 
下面上代码:

#父类
class Person():
    def __init__(self,name=None,age=None,sex=None):
        self.name=name
        self.age=age
        self.sex=sex
    def eat(self):
        print("%s正在吃饭"%self.name)

#学生子类:继承人类父类的属性
class Student(Person):
    def __init__(self,name=None,age=None,sex=None,score=None):
        # self.name=name
        # self.age=age
        # self.sex=sex
        #Person.__init__(self,name,age,sex)
        super().__init__(name,age,sex)
        self.score=score
    def study(self):
        self.eat()
        print("%s在学习,考了%d分"%(self.name,self.score))
    #方法的重写,调用的时候调用子类的方法
    #可以对自定义的方法进行重写
    def eat(self):
        print("%d的%s正在吃饭,他是%s的"%(self.age,self.name,self.sex))
    #也可以对自带的object类的方法进行重写。
    def __str__(self):
        return "姓名:{0},年龄:{1},性别:{2},成绩:{3}".format(self.name,self.age,self.sex,self.score)
    def __lt__(self,other):
        """ if isinstance(other,Student):
            return self.age<other.age
        else:
            return False """
        if self.name==other.name:
            return self.age<other.age
        else:
            return self.name<other.name
#实例化
stu=Student("汤姆",20,"男",80)
stu.study()
stu.eat()
list1=[]
stu1=Student("杰克",20,"男",90)
stu2=Student("杰森",21,"男",20)
stu3=Student("杰森",12,"女",50)
list1.append(stu)
list1.append(stu1)
list1.append(stu2)
list1.append(stu3)
for student in list1:
    print(student)
list1.sort()
for student in list1:
    print(student)

Python支持多重继承,一个子类可以继承多个父类。继承的语法格式如下:
class 子类类名(父类1[,父类2,...])

class A:
    def __init__(self,a=None):
        self.a=a
    def test(self):
        print("A...test")
class B:
    def __init__(self,b=None):
        self.b=b
    def test(self):
        print("B...test")
class C(B,A):
    def __init__(self,a):
        A.__init__(self,a)
    def t(self):
        A.test(self)#调用A的test()
        super().test()#这个调用的也是B的test
        print("C....t")
c=C("aa")
#默认调用的是父类B的test方法,因为在class C(B,A),B在A前面
c.test()
c.t()

如果在类定义中没有指定父类,默认父类是object类,也就是说,object是所有类的父类,里面定义了一些所有类共有的默认实现,如:__new__()。
定义子类时,必须在其构造函数中调用父类的构造函数。调用格式如下:
父类名.__init__(self,参数列表)

class Person:
    def say_age(self):
        print('不知道')
class Student(Person):#子类中为空
    pass
s = Student()
s.say_age()

 运行结果为:不知道
从上面一个简单地例子来看,子类Student已经继承了父类Person,并且可以自由调用方法。

class Person:
    def __init__(self,name,age):
        self.name = name
        self.__age = age  #私有属性
    def say_age(self):
        print('不知道')
class Student(Person):
    def __init__(self,name,age,score):
        Person.__init__(self,name,age)  #引用中形参是子类中的形参,不是父类中的。而且必须显式的调用,不然解释器不会调用
        self.score = score
s = Student('cys',18,100)
s.say_age()
print(s.name)
print(s._Person__age)

 运行结果为:不知道
cys
18
从上面代码中可以看出,继承成功后子类一样可以调用父类中的属性,私有属性继承后相当于子类的私有属性,需要使用调用私有属性的方法调用。

 多态

当子类和父类都存在相同的方法时,我们说,子类的方法覆盖了父类的方法,在代码运行的时候,总是会调用子类的方法。这样,我们就获得了继承的另一个好处:多态。(指同一个方法调用由于对象的不同会产生不同的行为。)

让用户输入要选择的汉堡,他不需要知道内部是如何制作的,只要得到一个选择的汉堡实例对象就可以

#创建汉堡的父类,并根据父类创建几个子类
class Hamburger:
    def make(self):
        print("您没有正确选择要制作的汉堡,请重新输入")
class FishHamburger(Hamburger):
    def make(self):
        print("您的鱼肉汉堡已经制作好了")
class BeafHamburger(Hamburger):
    def make(self):
        print("您的牛肉汉堡已经制作好了")
class ChickenHamburger(Hamburger):
    def make(self):
        print("您的鸡肉汉堡已经制作好了")
#工厂类,用来判断用户输入的值并创建相应的对象
class HamburgerFactory:
    @classmethod
    def getinput(cls,temp):
        if temp=="1":
            ch=FishHamburger()
        elif temp=="2":
            ch=BeafHamburger()
        elif temp=="3":
            ch=ChickenHamburger()
        else:
            ch=Hamburger()
        return ch
#主方法,通过用户输入的值调用工厂的类方法
while True:
    temp=input("请输入您要制作汉堡的序号,1.鱼肉汉堡,2.牛肉汉堡,3.鸡肉汉堡")
    if temp=="1" or temp=="2" or temp=="3":
        ch=HamburgerFactory.getinput(temp)
        ch.make()
        break
    else:
        ch=Hamburger()
        ch.make()
        continue

 补充

通过类的方法mro()或者类的属性_mro_可以输出这个类的继承层次结构。

通过类的方法dir()查看对象属性

lass A:
    pass
class B(A):
    pass
class C(B):
    pass
#mro()查看类的继承层次结构
print(C.mro())   #或者用 print(C.__mro__)
#dir()查看对象属性
a=A()
print(dir(a))

#结果如下:
[<class '__main__.C'>, <class '__main__.B'>, <class '__main__.A'>, <class 'object'>]
['__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__']

第一次出这么详细的东西,不对的地方还请多多指教,平时学业繁忙,在准备专升本,见谅

  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值