【Python】面向对象封装、继承、多态

【Python】面向对象封装、继承、多态

封装

1、封装的本质就是隐藏,将一些复杂的执行过程隐藏起来,留下调用的接口(接口就是函数,成为接口函数;一组接口函数的集合体构成一个接口),通过这些接口进行交互。
2、数据封装的主要原因有:保护隐私
3、方法封装的主要原因有:隔离复杂度
4、封装分为两个层面:
第一层面的封装:创建类或者对象,通过类名.或者对象名.的方式调用对应的方法,类名.对象名.就是访问隐藏属性的接口
第二层面的封装:类中把某些属性和方法隐藏起来(即定义为私有),只在类的内部使用,外部无法访问,或者留少量的接口(函数)供外部访问。

  • 第一层封装
    使用构造方法将内容封装到对象中,通过对象直接或者self间接调用被封装的内容
# coding=utf-8
class A:
    def __init__(self, name, age):
        self.name = name
        self.age = age

    def Aname(self):
        print "名字是:%s" %(self.name)

    def Aage(self):
        print "年龄是:%d" %(self.age)

a = A('Alice', 10)
a.Aname()
a.Aage()

程序输出:

名字是:Alice
年龄是:10
  • 第二层封装
    在Python中使用双下划线的方式实现隐藏属性(私有)。类中所有双下划线开头的名称如:__x都会自动变成_类名.__x的形式
    1.示例:将一个类定义如下
class A:
    __x = 1
    def __test(self):
        print 'private test'

(1)查看A的属性

print A.__dict__

#程序输出:
{'__module__': '__main__', '__doc__': None, '_A__test': <function __test at 0x00000000032BE128>, '_A__x': 1}

(2)调用__x
直接调用失败

print A.__x

#输出:类中没有`__x`,`__x`为私有的,不可以调用
Traceback (most recent call last):
  File "*******", line 6, in <module>
    print A.__x
AttributeError: class A has no attribute '__x'

通过A._A__x的形式调用

print A._A__x

#程序输出:
#得到正确输出1
1

(3)实例化A,并调用__x__test

a = A() #实例化
print a.__dict__ 
print a._A__x #对象的调用
a._A__test() #强制访问,对象的调用

#程序输出:
{}
1
private test

2.在继承中,父类如果不想让子类覆盖自己的方法,可以将方法定义为私有的

# 1、正常情况下:
class A:
    def fa(self):
        print('from A')
    def test(self):
        self.fa()
class B(A):
    def fa(self):
        print('from B')
b = B()
b.test() #b.test在父类A中找到了test(),得到b.fa()。然后在对象b中找到了B类中的fa方法,输出from B

# 执行结果:
from B

# 注意:时刻谨记:在定义阶段就会变形
# 2、把fa定义成私有的,即__fa
class A:
    def __fa(self):   #_A__fa
        print('from A')
    def test(self):  #在定义阶段就会变形
        self.__fa()   #self._A__fa
class B(A):
    def __fa(self):   #_B__fa
        print('from B')
b = B()  #实例化
b.test()  #自己的对象和类名称空间没有,在父类的名称空间找到,函数已经变形。

#执行结果:
from A

继承

新式类和旧式类

python在2.2版本中引入了descriptor功能,也正是基于这个功能实现了新式类(new-styel class)的对象模型,
同时解决了之前版本中经典类(classic class)系统中出现的多重继承中的MRO(Method Resolution Order)的问题,同时引入了一些新的概念,比如classmethod, staticmethod, super,Property等,这些新功能都是基于descriptor
而实现的。

  • 创建方法
    新式类是在创建的时候继承内置object对象(或者是从内置类型,如list,dict等),而经典类是直接声明的。

新式类:

class A(object):
    pass

旧式类:

class A():
    pass
  • 继承
    新式类在查找时的策略为广度优先
    旧式类在查找时的策略为深度优先
    可以利用 类名.__mro__的方法查看类之间的继承关系(旧式类没有这种方法)

新式类继承

class A(object):
    def foo1(self):
        print "A"
class B(A):
    def foo2(self):
        pass
class C(A):
    def foo1(self):
        print "C"
class D(B, C):
    pass

d = D()
d.foo1()
print D.__mro__


#程序输出:
#广度优先:D-->B-->C(找到fool()-->输出C)
C
(<class '__main__.D'>, <class '__main__.B'>, <class '__main__.C'>, <class '__main__.A'>, <type 'object'>)

旧式类继承

class A():
    def foo1(self):
        print "A"
class B(A):
    def foo2(self):
        pass
class C(A):
    def foo1(self):
        print "C"
class D(B, C):
    pass

d = D()
d.foo1()


#程序输出
#深度优先:D-->B-->A(找到fool())-->输出A
A

多态

  • 定义

    1. 多态(从定义角度出发):同一类事物的多种形态。例如:动物的多种形态–>狗、猫、猪
    2. 多态性(从使用角度出发):同一种调用方式,不同的执行效果。具有不同功能的函数可以使用相同的函数名,这样就可以用一个函数名调用不同内容的函数。
    3. 多态性依赖于:继承和定义的接口。
    4. 多态性的实质:定义了一个函数接口,在这个函数中定义了所有类内通性的功能,只要传入参数(对象名)函数调用执行,就得到不同的结果。这就是所谓的一种调用方式,不同的执行结果。
# coding=utf-8
class Animal:
    def run(self):
        raise AttributeError('子类必须实现这个方法')
class Dog(Animal):
    def run(self):
        print 'dog is running'
class Cat(Animal):
    def run(self):
        print 'cat is running'
class Pig(Animal):
    def run(self):
        print 'pig is running'

dog = Dog()
cat = Cat()
pig = Pig()

#定义统一的接口
def func(obj): #obj这个参数没有类型限制,可以传入不同类型的值
    obj.run() #调用的逻辑都一样,执行的结果却不一样

func(dog)
func(cat)
func(pig)


#程序运行结果:
dog is running
cat is running
pig is running
  • 多态的好处
    1. 增加了程序的灵活性
      以不变应万变,不论对象千变万化,使用者都是同一种形式去调用
    2. 增加了程序的扩展性
      通过继承父类创建了一个新的子类,使用者无需更改自己的代码,还是用定义的接口函数去调用。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值