代码改变世界

Python面向对象

2021-12-14 14:56  何小六soso  阅读(36)  评论(0编辑  收藏  举报

面向对象三大特性:封装、继承、多态

封装

封装就是用特殊的语法,对成员属性和成员方法进行包装,达到保护和隐藏的目的

但是封装是为了限制一些访问和操作,不能全部限制

被封装的成员只是限制了访问的权限,并不是不让访问

通常情况下,被封装的成员主要是提供内部使用

# 封装

'''
被特殊语法封装的成员,会有不同的访问权限,主要供内部使用
封装的级别:
                    公有:public   受保护:_protected   私有:__private
类外部是否可以访问       Y              Y(python可以)       N
'''


class Person():
    # 成员属性
    name = None
    _age = None
    __address = None

    # 成员方法
    def _say(self):
        print('hello python')

    def sing(self):
        print('唱歌')

    def __eat(self):
        print('吃饭')

    def __init__(self, name, age, address):
        self.name = name
        self.age = age
        self.address = address


tim = Person('python', 12, '北京')  # {'name': 'python', 'age': 12, 'address': '北京'}
# 对象的所有成员属性
print(tim.__dict__)

# 对象所有可执行方法
print(tim.__dir__())  # ['name', 'age', 'address', '__module__', 'say', 'sing', 'eat', '__init__', '__dict__',。。。。]
print(tim.name)  # None

print(tim._age)  # hello python

tim._say()

# tim.__eat() 报错

# print(tim.__address) # 报错

继承

计算机中的继承

在面向对象中,一个类继承了父类,那么这个类就拥有了父类中所有的成员(除私有成员)

继承概念

被其它类继承的类,称为父类也叫做基类或者超类

继承类叫做子类,或者派生类

继承的意义

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

语法格式

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

继承的特征:

  • 不指定继承父类时,所有类都继承Object

  • 子类继承父类后就拥有了父类中的所有成员属性和成员方法 (除了私有化成员和方法)

  • 子类继承父类后只是引用父类的成员属性和方法,并不是父类

  • 子类继承父类后可以重写父类中的成员方法,叫做方法的重写

  • 重写父类方法后,子类可以使用super().func()方式继续调用父类被重写的方法

  • 子类如果定义了父类中不存在的方法,叫做对父类的扩展

# 继承
'''
当子类继承父类后,就可以使用父类的成员属性和方法(除私有成员)
子类可以有自己独立的成员
子类继承父类后,重新定义了父类中的方法,这种情况称为对父类方法的重写
子类继承父类后,定义父类中没有的方法,称为对父类的扩展
一个父类可以被多个子类继承
子类调用父类的方法时,如果该方法有参数要求,也需要传递参数
'''
import time


# 定义猫科动物
class Felidae():
    # 属性
    color = '花色'
    sex = 'man'

    def running(self):
        print('奔跑的猫科动物')

    def eat(self):
        print('吃饭的小猫')


# 定义猫类
class Cat(Felidae):
    # 定义私有属性
    age = 11

    # 重写父类方法
    def eat(self):
        print('子类重写父类的小猫吃饭方法')
        # 在子类中使用被子类重写的父类方法
        super().eat()  # 吃饭的小猫

    # 扩展父类方法
    def play(self):
        print('小猫在玩老鼠')


# 实例化对象
c = Cat()

print(c.__dict__)  # {}

print(c.color)  # 花色

c.running()  # 奔跑的猫科动物

c.eat()  # 子类重写父类的小猫吃饭方法

c.play()  # 小猫在玩老鼠

# 使用私有属性
print(c.age)  # 11

单继承和多继承

单继承

一个类只能继承一个父类

一个父类可以被多个子类继承,还可以存在链式继承

链式继承:继承父类的子类后子类被另外子类继承 (B被A继承,A被C继承)

多继承

一个类可以继承多个父类

​ 语法格式:

class 父亲():
	pass
class母亲():
	pass
....
class 子类(父亲,母亲,...):
	pass
# 多继承

# 父亲类
class F():
    def sing(self):
        print('父亲在唱歌')


class M():
    def sing(self):
        print('母亲在唱歌')


class Sun(F, M):
    def sing(self):
        # Sun(F,M),F在前时默认调用F
        super().sing()  # 类父亲在唱歌
        print('儿子在唱歌')


# 实例化对象
s = Sun()
s.sing()  # 儿子在唱歌

菱形继承(钻石继承)

	A
B		D
	C
# 菱形继承

# 爷爷类
class HuMan():
    age = 60

    def sing(self):
        print('爷爷在唱歌')


# 父亲类
class F(HuMan):
    age = 35

    def sing(self):
        super().sing()  
        print(super().age)  
        print('父亲在唱歌')


# 母亲类
class M(HuMan):
    age = 33

    def sing(self):
        super().sing()  
        print(super().age)  
        print('母亲在唱歌')


# 儿子类
class Sun(F, M):
    age = 5

    def sing(self):
        super().sing()  
        print(super().age)  
        print('儿子在唱歌')


s = Sun()

s.sing()
'''
继承关系:
    s-->F-->M--HuMan  
print结果:
    爷爷在唱歌
    60
    母亲在唱歌
    33
    父亲在唱歌
    35
    儿子在唱歌
'''

#mro() 获取MRO列表,就是类的继承关系
print(Sun.mro()) # [<class '__main__.Sun'>, <class '__main__.F'>, <class '__main__.M'>, <class '__main__.HuMan'>, <class 'object'>]		

​ MRO(MRP Reation Prder)

MRO列表生成原则:
	1.子类永远在父类的前面
	2.同等级的类,按照子类继承顺序排序
	3.先子类后父类的顺序原则,最后的类是系统提供的Object类
	[<class '__main__.Sun'>, <class '__main__.F'>, <class '__main__.M'>, <class '__main__.HuMan'>, <class 'object'>]

​ super()

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

类关系检测 issubclass()

issubclass() 检测一个类是否是另外一个类的子类

class A():
    print('A类')


class B(A):
    print('B类')


class C(B):
    print('C类')


class D(C):
    print('D类')


res = issubclass(B, A)  # 检查B类是不是A类的子类  True
print(res)
res = issubclass(D, A)  # 检查S类是不是A类的子类  True
print(res)
res = issubclass(A, C)  # 检查A类是不是C类的子类  False
print(res)

多态

同一个方法,调用的对象不同,产生了不同形态的结果,这种现象叫做多态

​ 普通写法实现

# 多态

# 同一个方法,调用的对象不同,产生了不同形态的结果,这种现象叫做多态

# 定义电脑类

class Computer():
    # 在电脑类中定一个usb的规范接口 方法,在方法中传递一个对象,实现多态功能
    def usb(self, obj):
        obj.start()


# 定义鼠标类
class Mousr():
    def start(self):
        print('鼠标插入成功,可以正常使用')


# 定义键盘类
class KeyBord():
    def start(self):
        print('键盘接入成功,可以正常启动')


# 定义U盘类
class UDisk():
    def start(self):
        print('U盘接入成功,可以正常使用')


# 实例化对象
c = Computer()  # 电脑对象
m = Mousr()  # 鼠标对象
k = KeyBord()  # 键盘对象
u = UDisk()  # U盘对象

# 把不同的设备插入到电脑的usb接口中
c.usb(m)  # 鼠标插入成功,可以正常使用
c.usb(k)  # 键盘接入成功,可以正常启动
c.usb(u)  # U盘接入成功,可以正常使用

​ 继承方法实现

# 多态 继承版

"""
定义一个接口规范类,其它类都继承这个类,并重新父类的方法
由于每一个对象都实现父类方法的方式都不同,最后的结果也是不一样的
"""


# 定义USB类
class USB():
    """
    当前类说明:
        这个类只是一个接口规范类,需要子类继承并实现start方法
        start方法不做任何具体功能的实现
    """
    # 在接口中规定一个规范的接方法,但不实现功能
    def start(self):
        pass


# 定义鼠标类
class Mousr(USB):
    def start(self):
        print('鼠标接入成功,可以正常使用')


# 定义键盘类
class KeyBord(USB):
    def start(self):
        print('键盘接入成功,可以正常启动')


# 定义U盘类
class UDisk(USB):
    def start(self):
        print('U盘接入成功,可以正常使用')


# 实例化对象
c = Computer()  # 电脑对象
m = Mousr()  # 鼠标对象
k = KeyBord()  # 键盘对象
u = UDisk()  # U盘对象

m.start()  # 鼠标接入成功,可以正常使用
k.start()  # 键盘接入成功,可以正常启动
u.start()  # U盘接入成功,可以正常使用