python面向对象之封装、继承、多态

封装

将属性私有化,定义公有set和get方法

  • 方法一
class Person:
    def __init__(self):
        self.__name = '小明'
        self.__age = 15

    def setAge(self,age):
        self.__age = age

    def getAge(self):
        print(self.__age)

    def getName(self):
        print(self.__name)

if __name__ == '__main__':
    xiaoming = Person()

    # 无法直接访问属性 __name,__age
    xiaoming.getName()
    
    # 更改小明的年龄
    xiaoming.setAge(20)
    xiaoming.getAge()
    
	# 查看类的所有属性和方法
    print(dir(xiaoming))
    print(xiaoming.__dir__())

输出结果

小明
20
['_Person__age', '_Person__name', '__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__', 'getAge', 'getName', 'setAge']
['_Person__name', '_Person__age', '__module__', '__init__', 'setAge', 'getAge', 'getName', '__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__']

可以看出属性私有化的本质:在对象的私有属性前添加_类名(_Person__age,_Person__name)

  • 方法二 :使用装饰器
class Student:
    def __init__(self):
        self.__name = '小红'

    @property
    def name(self):
        return self.__name

    @name.setter
    def name(self,name):
        self.__name = name
        
if __name__ == '__main__':
    xiaohong = Student()
    # 不使用赋值= 默认调用getter方法
    print(xiaohong.name)

	# 使用赋值= 默认使用setter方法
    xiaohong.name = '王涵'
    print(xiaohong.name)

继承

在Python中,支持多继承。

  • 示例一(单继承):
class Person:
    def __init__(self,name):
        self.name = name

class Student(A):
    def __init__(self):
        super(B, self).__init__("小明")
        self.age = 15

    def __str__(self):
        return '姓名:{},年龄:{}'.format(self.name,self.age)

if __name__ == '__main__':
    xiaoming = Student()
    print(xiaoming)

输出结果:

姓名:小明,年龄:15

python 多重继承的方法解析顺序

任何实现多重继承的语言都要处理潜在的命名冲突, 这种冲突由不相关的祖先类实现同名方法引起
在这里插入图片描述

  • 示例二(多继承,使用较少):
class A:
    def say(self):
        print("A Hello:", self)

class B(A):
    def eat(self):
        print("B Eating:", self)

class C(A):
    def eat(self):
        print("C Eating:", self)

class D(B, C):
    def say(self):
        super().say()
        print("D Hello:", self)

    def dinner(self):
        self.say()
        super().say()
        self.eat()
        super().eat()
        C.eat(self)

if __name__ == '__main__':
    d = D()
    d.eat()

    #d.dinner()

这里B和C都实现了eat方法,

在 D 的实例上调用 d.eat() 方法的话, 运行的是哪个 eat 方法呢?

>>> d = D()
>>> d.eat()
B Eating: <__main__.D object at 0x7fb90c627f60>
>>> C.eat(d)
C Eating: <__main__.D object at 0x7fb90c627f60>
超类中的方法都可以直接调用, 此时要把实例作为显式参数传入

Python 能区分 d.eat() 调用的是哪个方法, 是因为 Python 会按照特定的顺序遍历继承图。 这个顺序叫方法解析顺序( Method Resolution Order, MRO)。 类都有一个名为 mro 的属性, 它的值是一个元组, 按照方法解析顺序列出各个超类, 从当前类一直向上, 直到object 类。 D 类的 mro 属性如下 :

# 输出元组
print(D.__mro__)

# 输出列表
print(D.mro())

输出:

(<class '__main__.D'>, <class '__main__.B'>, <class '__main__.C'>, <class '__main__.A'>, <class 'object'>)
[<class '__main__.D'>, <class '__main__.B'>, <class '__main__.C'>, <class '__main__.A'>, <class 'object'>]

新式类、经典类

在Python 3.x中取消了经典类,默认都是新式类,并且不必显式的继承object,也就是说:
class Person(object):pass
class Person():pass
class Person:pass
三种写法并无区别,推荐第一种

但是在Python2.x中,默认都是经典类,只有显式继承了object才是新式类,即:
class Person(object):pass 新式类写法
class Person():pass 经典类写法
class Person:pass 经典类写法

他们最明显的区别在于继承搜索的顺序发生了改变,即
经典类多继承搜索顺序(深度优先):
先深入继承树左侧查找,然后再返回,开始查找右侧

新式类多继承搜索顺序(广度优先):
先在水平方向查找,然后再向上查找


多态

在python中没有严格的多态概念。总是伴随着继承使用的。若后续有学习,继续补充。

发布了50 篇原创文章 · 获赞 4 · 访问量 1369

猜你喜欢

转载自blog.csdn.net/weixin_43999327/article/details/103680315