Python Note -- Day 12. 面向对象 - 三大特性

18 面向对象 - 三大特性

封装 继承 多态

18.1 封装

封装是使用特殊的语法,对成员属性和成员方法进行包装,达到保护和隐藏的目的
封装是为了限制一些访问和操作,但是不能全部都限制
被封装的成员只是限制了访问的权限,并不是不让访问
通常情况下,被封装的成员主要是供类的内部使用

18.1.1 封装的级别

被特殊语法封装的成员,会有不同的访问权限

'''
         公有的 public   受保护的 protected    私有的 private
在类的内部       ok             ok                 ok
在类的外部       ok             no                 no      
'''

在成员前面加一个_,受保护的成员
在成员前面加两个__,私有的

了解即可:
python中,对成员进行私有化,其实就是改了成员的名字,并不是真正的私有化
受保护 _成员
私有化 _类名__成员 (可以据此访问)

class Person():
    name = 'one'
    _age = 'one'
    __sex = 'None'

    def __init__(self,n,a,s):
        self.name = n
        self._age = a
        self.__sex = s

    def func(self):
        # 在类的内部,可以操作任一成员
        print(self._age)
        print(self.__sex)
        self._sing()

    def __talk(self):
        print('gossip and chatting')

    def _sing(self):
        print('sing ambitiously and loudly')

one = Person('yangmi','30','female')
# print(one.age)   # 不可访问
# print(one.sex) # 不可访问
# one.sing()
one.func()
print(one._age)

# 据此访问 protected private
print(one._age)
print(one._Person__sex)
one._sing()

18.1.2 查看对象的成员

# 查看对象的所有成员
print(one.__dict__)  # 可以获取对象自己的所有成员信息
# {'name': 'yangmi', 'age': '30', 'sex': 'female'}
print(Person.__dict__) # 可以获取当前类的所有成员信息
# {'__module__': '__main__', 'name': 'one', 'age': 'one', 'sex': 'None', '__init__': <function Person.__init__ at 0x0000000001E69318>, 'talk': <function Person.talk at 0x0000000001E693A8>, 'sing': <function Person.sing at 0x0000000001E69438>, '__dict__': <attribute '__dict__' of 'Person' objects>, '__weakref__': <attribute '__weakref__' of 'Person' objects>, '__doc__': None}
# print(one.__dir__())
# ['name', 'age', 'sex', '__module__', '__init__', 'talk', 'sing', '__dict__', '__weakref__', '__doc__', '__repr__', '__hash__', '__str__', '__getattribute__', '__setattr__', '__delattr__', '__lt__', '__le__', '__eq__', '__ne__', '__gt__', '__ge__', '__new__', '__reduce_ex__', '__reduce__', '__subclasshook__', '__init_subclass__', '__format__', '__sizeof__', '__dir__', '__class__']

18.2 继承

一个类继承父类,这个类就拥有了父类中的所有成员,除了私有成员

18.2.1 继承的概念

被其他类继承的类,称为 父类 ,也叫 基类 或者 超类
继承其他类的类,称为 子类,也叫 派生类

继承的意义:

提高代码的重用性,建立新的类与类的关系,方便其他逻辑的操作

18.2.2 继承的语法格式

class 父类():
    pass
class 子类(父类):
    pass

特征:

  • 在不指定继承的父类时,所有类都继承自系统提供的object类
  • 子类继承父类,拥有了父类中的所有成员,包括魔术方法(除了私有成员)
  • 子类继承父类,不会把父类复制给子类,而是引用父类
  • 子类继承父类,可以重写父类中的方法,也可扩展父类没有的方法
  • 子类重写父类方法,之后依然可以调用父类的方法,使用super().父类方法()的方式

子类可以有自己独立的成员,也可以没有

若子类继承父类后,重新定义了父类的方法,这种情况称为对父类方法的 重写
若子类继承父类后,定义了父类没有的方法,这种情况称为对父类方法的 扩展

子类调用方法时,若该方法有参数要求,需要传递参数

  • 一个父类可以被多个子类继承,还可以存在 链式继承
    链式继承:A类继承B类,B类继承C类,C类继承D类。。。
class Felid():
    color = 'white'
    variety = ''
    age = ''

    def run(self):
        print('better run run')

    def crawl(self):
        print('climb up the tree')

class Cat(Felid):
    def crawl(self):
        # 子类中调用父类方法
        super().crawl()
        print('climb the shelf')

class Predator():
    def feature1(self):
        print('prey the prey')

class Puma(Felid,Predator):
    pass

# 实例化
h = Cat()
# 调用成员时,先查对象自己的属性,==》 对象的类的属性,==》 父类的属性
h.run()
print(h.__dict__)  # {}
# 继承关系 是继承引用,没有复制一份给子类
h.crawl()
b = Puma()
b.run()
b.feature1()

18.2.3 多继承

单继承:一个类只能继承一个父类的方式
多继承:一个类key继承多个父类的方式
注意!
多继承中,在子类调用父类方法时,super().父类方法() 调用的是第一个父类!

18.2.4 菱形继承 (钻石继承)

D类继承了B类和C类,然后B类和C类又分别继承了A类,这种继承关系称为 菱形继承

   A
 B   C
   D
class Human():
    num = 44
    def eat(self):
        print(self.num)
        print(self)
        print('can eat raw meat')

class F(Human):
    num = 33
    def eat(self):
        super().eat()
        print(super().num)
        print('eat meat with excellent appetite')

class M(Human):
    num = 22
    def eat(self):
        super().eat()
        print(super().num)
        print('eat with grace manner')

class Son(F,M):
    num = 11
    def eat(self):
        super().eat()
        print(super().num)
        print('eat as he likes')

a = Son()
a.eat()
# 每个子类FMS都有super().eat(),所有的方法都输出
# 子类S和第一个副子类F有,除了父类,其他都输出
# 子类S,M 有,输出F和S的方法
# 只有子类有,输出F和S的方法
# print(a.num)
'''
11
<__main__.Son object at 0x00000000021FD508>
can eat raw meat
44
eat with grace manner
22
eat meat with excellent appetite
33
eat as he likes
'''

mro( ) 获取mro列表,就是类的继承关系

print(Son.mro())

super( )

使用super去调用父级的方法时,实际上就是用super调用MRO列表中的上一级中的方法;
使用super去调用父级的属性时,实际上就是用super调用MRO列表中的上一级中的属性;
super()本身调用父级方法时,传递的self对象,就是这个方法中的那个self对象自己:
如,用a实例化的对象Son,方法中的self,就是a,之后super传递到上一级,self=a也一起传递,以此类推,整个调用过程self都只有a

18.2.5 继承关系检测

在实现继承的语法后,程序会自动生成一个继承的列表MRO(Method Relation Order)方法关系列表
MRO列表生成原则
1.子类永远在父类的前面
2.同一等级的类,按照子类中的继承顺序摆放
2.先子类,后父类的顺序原则,最终的类为系统提供的object类

MRO 调用方法:类名.mro()

  • super()调用时,并不是查找父类,而是去MRO列表找上一个类
  • super()调用时,会自动把当前self传入到上一级的类的方法中

类关系检测 issubclass()

检测一个类是否是另一个类的子类

class A:
    pass
class B(A):
    pass
class C(A):
    pass
class D(B,C):
    pass

# 获取类的MRO列表
print(D.mro())
# [<class '__main__.D'>, <class '__main__.B'>, <class '__main__.C'>, <class '__main__.A'>, <class 'object'>]
# 检测类是否是另一个类的子类
res = issubclass(D,A)
print(res)

18.3 多态

对于同一个方法,由于调用对象(或者传入对象)的不同,产生了不同形态的结果
简单方法:

# 定义电脑类
class Computer():
    # 在电脑类中定义一个usd 的规范的接口的方法
    def usb(self,obj):
        obj.start()         # 注意!

# 定义鼠标类
class Mouse():
    def start(self):
        print('active mouse successfully, u can double click')

# 定义键盘类
class KeyBoard():
    def start(self):
        print('u can use keyboard now !')

# 定义U盘类
class Udisk():
    def start(self):
        print('active usb ')

# 实例化对象
c = Computer()
m = Mouse()
k = KeyBoard()
u = Udisk()

# 把不同的设备插入电脑的usb接口中
c.usb(m)
c.usb(k)

18.4 多态 - 继承版

'''
定义一个接口规范类,其它类都继承这个类,并实现(重写)父类中的方法
由于每个对象实现父类方法的方式或者过程都不相同,最后的结果是不一样的形态
'''
# 定义 USB 类
class USB():
    '''
    当前类的说明:
    这个类是一个接口规范类,需要子类继承并实现start方法
    start方法不作任何具体功能的实现
    '''
    # 在USB中定一个规范的借口方法,但是不实现任何功能
    def start(self):
        pass
# 定义鼠标类
class Mouse(USB):
    def start(self):
        print('active mouse, u can double click')

# 定义键盘类
class KeyBoard(USB):
    def start(self):
        print('u can use keyboard now !')

# 定义U盘类
class Udisk(USB):
    def start(self):
        print('active usb ')

r = issubclass(Mouse,USB)
# 实例化对象
m = Mouse()
k = KeyBoard()
u = Udisk()
m.start()
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值