面向对象-继承和多态

Posted guyanzhi

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了面向对象-继承和多态相关的知识,希望对你有一定的参考价值。

在这一节中,你将体会到面向对象的诸多特色.

1、单继承

class Person(Object):
    def __init__(self, name, age):
        self.name = name
        self.age = age

    def walk(self):
        print("%s is walking..." % self.name)

    def talk(self):
        print("%s is talking..." % self.name)


# 定义子类1  py23都支持
class Teacher(Person):
    def __init__(self, name, age, level):
        super(Teacher, self).__init__(name, age)  # python提供了这个函数,创建一个父类的对象,用来调用父类的__init__()
        # 避免了再次定义这些属性
        self.level = level

    def walk(self):  # 继承父类的方法并 拓展 实践中,继承的这种用途意义并不很大,甚至常常是有害的。因为它使得子类与基类出现强耦合。
        super().walk()  # 避免再写一遍父类中的功能代码
        print("加速...")

    def teach(self):
        print("%s is teaching..." % self.name)


# 定义子类2
class Student(Person):
    def __init__(self, name, age, grade):
        Person.__init__(self, name, age)  # 这样写避免了自己再次定义这些属性
        self.grade = grade

    def fight(self):
        print("%s is fighting..." % self.name)


t1 = Teacher("mr z", 30, "一级")
s1 = Student("xiao ming", 15, "高中一年级")

 所谓继承,就像上述代码中,定义Person 类时,class Person(Object)  表示Person 类拥有Object 类的属性和方法(一些内置方法和属性),class Teacher(Person),Teacher 类拥有Person 类的属性和方法...

(walk和talk). Person 是Teacher 的父类(基类、父类或超类(Base class、Super class)),Teacher 是Person 的子类..父类上还可以有父类,子类下也可以还有子类,这就是继承关系.

Python 有两个判断继承的函数:isinstance() 用于检查实例类型;issubclass() 用于检查类继承。参见下方示例:

class Person(object):
    pass

class Child(Person):                 # Child 继承 Person
    pass

May = Child()
Peter = Person()    

print(isinstance(May,Child))         # True
print(isinstance(May,Person))        # True
print(isinstance(Peter,Child))       # False
print(isinstance(Peter,Person))      # True
print(issubclass(Child,Person))      # True

 

2、多继承

多继承是指一个类有多个父类的情况.多继承使用的比较少,但是你需要知道,多继承时,是怎样的继承顺序:首先提出两个概念:新式类和经典类.

新式类:python3中默认所有的类都是新式类:以Object为最终的父类(我喜欢叫它 祖先类) 创建对象时需要申请名称空间 将对象属性放进去 这些事情在新式类里 都是objeck类自动执行

经典类:python2中,继承于哪个类都需要在()里说明 ,没有显式的继承object类的类,以及该类的子类,都是经典类

 

有的地方会这样定义新式类和经典类:

Python 与其他语言不同点在于,当我们定义一个 class 的时候,我们实际上就定义了一种数据类型。我们定义的数据类型和Python自带的数据类型,比如str、list、dict没什么两样。
由任意内置类型派生出的类(只要一个内置类型位于类树的某个位置),都属于“新式类”,都会获得所有“新式类”的特性.反之,即不由任意内置类型派生出的类,则称之为“经典类”。
“新式类”和“经典类”的区分在Python 3之后就已经不存在,在Python 3.x之后的版本,因为所有的类都派生自内置类型objec.(即使没有显示的继承object类型),即所有的类都是“新式类”。

大抵上是一致的.

 

经典列和新式类在继承顺序(继承的查找)方式山有区别:

新式类的继承顺序是按照C3算法来的

经典类则是按照“从左至右,深度优先”的方式去查找属性。当有菱形继承时,祖先类最后查找.

了解 C3算法

 merge操作是C3算法的核心。

遍历执行merge操作的序列,如果一个序列的第一个元素,是其他序列中的第一个元素,或不在其他序列出现,则从所有执行merge操作序列中删除这个元素,合并到当前的mro中。

举例:

技术分享图片
# 简易的定义几个类
class A(object): pass


class B(object): pass


class C(object): pass


class E(A, B): pass


class F(B, C): pass


class G(E, F): pass

‘‘‘
O表示object类
A、B、C都继承至一个基类,所以mro序列依次为[A,O]、[B,O]、[C,O]
mro(E) = [E] + merge(mro(A), mro(B), [A,B])
       = [E] + merge([A,O], [B,O], [A,B])
执行merge操作的序列为[A,O]、[B,O]、[A,B]
A是序列[A,O]中的第一个元素,在序列[B,O]中不出现,在序列[A,B]中也是第一个元素,所以从执行merge操作的序列([A,O]、[B,O]、[A,B])中删除A,合并到当前mro,[E]中。
mro(E) = [E,A] + merge([O], [B,O], [B])
再执行merge操作,O是序列[O]中的第一个元素,但O在序列[B,O]中出现并且不是其中第一个元素。继续查看[B,O]的第一个元素B,B满足条件,所以从执行merge操作的序列中删除B,合并到[E, A]中。
mro(E) = [E,A,B] + merge([O], [O])
       = [E,A,B,O]
       
‘‘‘
C3算法

 

查看和判断继承有如下方法:

Python 有两个判断继承的函数:isinstance() 用于检查实例类型;issubclass() 用于检查类继承。参见下方示例:

技术分享图片
class Person(object):
    pass

class Child(Person):                 # Child 继承 Person
    pass

May = Child()
Peter = Person()    

print(isinstance(May,Child))         # True
print(isinstance(May,Person))        # True
print(isinstance(Peter,Child))       # False
print(isinstance(Peter,Person))      # True
print(issubclass(Child,Person))      # True
isinstance和issubclass

 

 类名.__bases__方法 返回该类继承于哪些类(多继承时的从左到右的类都将被返回)

类名.__base__方法 只返回从左到右继承的第一个类.

类名.__mro__或  类名.mro()  可以返回该类的查找顺序列表  在最上面的实例中 : print(Teacher.mro()) 打印[<class ‘__main__.Teacher‘>, <class ‘__main__.Person‘>, <class ‘object‘>]

 

在python3中,使用类和对象来编程,要求你能把握好类和对象的定义,比如一个学生管理系统中,有老师,学生,,这两个类应该有一个父类 Person,而不能将Teacher设置成Student的父类,即便Teacher

的 name age 等属性在Student中也有. 把握好这一"先抽象,后继承"的原则,在安排各种类和父类时就不易出错.

 

使用python3的新式类时,Object为默认的父类,所有的类都会继承它的一些属性和方法,它们的名称是以双下划线__开头,同时又以双下划线__结尾。

这些属性和方法不再是私有属性和私有方法,它们是可以在类的外部通过实例对象去直接访问的,且它们都有着各自特殊的意义,我们可以通过这些特殊属性和特殊方法来获取一些重要的信息,

或执行一些有用的操作。

属性:

属性名称
说明
__doc__ 类的描述性信息 类似函数的‘‘‘ ‘‘‘ 注释
__module__ 当前操作对象的类的定义所在模块名
__class__ 当前操作的对象的类名
__dict__ 一个字典,保存类的所有成员(属性和方法)或实例对象的成员属性

 

实例应用:

技术分享图片
class Dog(object):
    """这是一个Dog类"""
    # print(‘Hello, This is a dog.‘)
    color = 白色

    def __init__(self, name):
        self.name = name
        self.__id = 1234

    def func1(self):
        pass

    def __func1(self):
        pass

    @classmethod
    def func2(cls):
        pass

    @staticmethod
    def func3():
        pass
dog.py中定义Dog类
技术分享图片
from dog import Dog

dog1 = Dog(泰迪)
print(dog1.__doc__)
print(dog1.__module__)
print(dog1.__class__)
print(dog1.__dict__)
print(Dog.__dict__)
test.py中应用实例对象

 

 打印结果:

技术分享图片
这是一个Dog类
dog
<class dog.Dog>
{name: 泰迪, _Dog__id: 1234}
{__dict__: <attribute __dict__ of Dog objects>, __module__: dog, func2: <classmethod object at 0x000001DF0C658F98>, color: 白色, func3: <staticmethod object at 0x000001DF0C658FD0>, _Dog__func1: <function Dog.__func1 at 0x000001DF0C63E400>, __weakref__: <attribute __weakref__ of Dog objects>, __doc__: 这是一个Dog类, __init__: <function Dog.__init__ at 0x000001DF0C63E2F0>, func1: <function Dog.func1 at 0x000001DF0C63E378>}
View Code

 

 

方法:

方法 说明
__init__ 初始化构造方法,创建类时自动执行
__del__ 析构方法,当对象在内存中被释放(回收)前,会自动执行
__str__ 如果类中定义了__str__方法,并有返回值,在打印对象时会自动输出_-str__的返回值
__xxxitem__

是指__getitem__、__setitem__、__delitem这3个方法,它们用于索引操作,比如对字典的操作,分别表示 获取、设置、删除某个条目。 数据。可以通过这些方法来定义一个类对字典进行封装,

从而可以对字典中key的操作进行控制,尤其是删除操作。

__new__ 该方法会在__init__方法之前被执行,该方法会创建被返回一个新的实例对象,然后传递给__init__。另外需要说明的是,这不是一个成员方法,而是一个静态方法。
__call__ 源码中的注释是"Call self as a function." 意思是把自己(实例对象)作为一个函数去调用,而函数的调用方式是函数名()。也就是说,当我们执行实例对象()或者 类名()()这样的操作时会触发执行该方法。

示例:

 https://www.cnblogs.com/yyds/p/7591804.html 

 




以上是关于面向对象-继承和多态的主要内容,如果未能解决你的问题,请参考以下文章

0面向对象三大机制 封装继承多态

0面向对象三大机制 封装继承多态

面向对象的多态详解 !!

Python基础:面向对象-继承和多态

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

Python面向对象:继承多态类属性和类方法单例